思路:二分答案
分析:
1 首先我们遇到这类无从下手的题目的时候,我们首先应该考虑的就是利用二分答案,其它我们无从下手。
2 对于这道题,我们只要二分然后逼近答案即可。
3 这里对二分的时候返回的是right而不是mid做一个解释
我们观察二分的形式可以看到while(left <= right){},那么我们知道在得到答案之前的一步肯定是left = mid = right ;假设这个时候judge(mid)满足那么left = mid+1 ,mid = right ,既然满足就有ans = mid,所以这个时候返回right = mid正确;如果judge(mid)不满足那么right = mid-1, mid = left, 答案肯定不是mid那只能是right。所以可以得出二分的时候返回的是right。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 1010; const int N = 25; struct components{ char type[N]; char name[N]; int price; int qulity; }; components c[MAXN]; int n , budge; bool judge(int x){ int i , j , sum = 0; for(i = 0 ; i < n ;){ int Min = 2147483647; int pos = -1; for(j = i ; j < n && !strcmp(c[i].type , c[j].type) ; j++){ if(c[j].qulity >= x && Min > c[j].price){ pos = j; Min = c[j].price; } } if(pos == -1) return false; sum += Min; i = j; } return sum <= budge ? true : false; } int solve(int Min , int Max){ int left , right , mid; left = Min , right = Max; while(left <= right){ mid = (left+right)>>1; if(judge(mid)) left = mid+1; else right = mid-1; } return right;//返回的是right } int main(){ int Case; int Min , Max; scanf("%d" , &Case); while(Case--){ scanf("%d%d" , &n , &budge); Min = 2147483647 , Max = 0; for(int i = 0 ; i < n ; i++){ scanf("%s %s %d %d" , c[i].type , c[i].name , &c[i].price , &c[i].qulity); Min = min(Min , c[i].qulity); Max = max(Max , c[i].qulity); } int ans = solve(Min , Max);//这里爱原来的数组中求大于等于它的最小值,怕二分到的答案没在原数组中 for(int i = 0 ; i < n ; i++){ if(c[i].qulity >= ans) ans = min(ans , c[i].qulity); } printf("%d\n" , ans); } return 0; }