题目链接:点击打开链接
题意: 给n个组件来组装电脑, 每个组件有4个属性:种类、名称、价格、品质。 要求每种组件买一个, 求在不超过预算的情况下, 品质最低的品质尽量大。
思路:很显然, 二分最低品质, 然后判断是否可行, 属于二分找上界,在二分时有一个小技巧用来处理当区间相差1时的情况。
细节参见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;
const int mod = 1000000000 + 7;
const int INF = int(1e9);
const ll INF64 = ll(1e18);
const int maxn = 1000 + 10;
int T,n,b,cnt,val,pp;
struct node {
int val, p;
node(int val=0, int p=0):val(val), p(p) {}
bool operator < (const node& rhs) const {
return val < rhs.val;
}
};
vector<node> g[maxn];
map<string, int> p;
bool ok(int m) {
int ans = 0;
for(int i=0;i<cnt;i++) {
bool flag = false;
int len = g[i].size();
for(int j=0;j<len;j++) {
node &u = g[i][j];
if(u.p >= m) {
ans += u.val;
flag = true;
break;
}
}
if(!flag) return false;
if(ans > b) return false;
}
return true;
}
char s[100],name[100];
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&b);
p.clear();
for(int i=0;i<n;i++) g[i].clear();
cnt = 0;
int minv = INF, maxv = -INF;
for(int i=0;i<n;i++) {
scanf("%s%s%d%d",s,name,&val,&pp);
minv = min(minv, pp);
maxv = max(maxv, pp);
if(!p.count(s)) {
p[s] = cnt;
g[cnt].push_back(node(val, pp));
++cnt;
}
else {
int id = p[s];
g[id].push_back(node(val, pp));
}
}
for(int i=0;i<cnt;i++) {
sort(g[i].begin(), g[i].end());
}
int l = minv, r = maxv, mid;
while(r > l) {
mid = (l + r + 1) >> 1;
if(ok(mid)) l = mid;
else r = mid - 1;
}
printf("%d\n",l);
}
return 0;
}