uvalive 3971 Assemble
https://vjudge.net/problem/UVALive-3971
题意:
现在你要组装一台电脑,每个电脑的一种类型的配件都有多种选择,它们的名字是不同的。
现在给出已有的元件,每种类型都至少有一个元件。你有已知的预算,要求你找出以不超过预算的钱,每种类型的元件恰好选择一个,最低质量的元件的质量要尽量高,输出这个最高值。
思路:
从题意的叙述来看,最大化最小值,那么肯定是选用二分。
二分选择的量应该是质量。
接下来证明花费的钱是随着质量非递减的。
设当前的最小质量为x,那么把所有元件中质量小于x的全部删除,在剩下元件中,每一类型选择价钱最少的。
当x增加:
1.选择的价钱最少的恰好是质量最小的,那么此时质量选更大的话,价格的总和就有可能变大(会有重复的价格);
2.选择的价钱最少的不是质量最小的,那么当质量更大的话,选择的还是这个元件,价钱不会增加。
所以,当x逐渐增大的时候,价钱非递减,满足而二分的条件。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <string> 4 #include <map> 5 #include <vector> 6 using namespace std; 7 8 struct node 9 { 10 long long p,q; 11 }; 12 13 int cnt = 0; 14 vector<node> v[1005]; 15 int n; 16 long long b; 17 map<string,int> mmp; 18 19 bool meet(long long k) 20 { 21 long long sum = 0; 22 23 for (int i = 1;i <= cnt;i++) 24 { 25 long long minn = 1e15; 26 27 for (int j = 0;j < v[i].size();j++) 28 { 29 if (v[i][j].q >= k) 30 { 31 if (v[i][j].p < minn) 32 { 33 minn = v[i][j].p; 34 } 35 } 36 } 37 38 sum += minn; 39 } 40 41 return sum <= b; 42 } 43 44 int main() 45 { 46 int t; 47 48 scanf("%d",&t); 49 50 while (t--) 51 { 52 scanf("%d%lld",&n,&b); 53 54 for (int i = 0;i <= n;i++) v[i].clear(); 55 56 mmp.clear(); 57 58 cnt = 0; 59 60 for (int i = 0;i < n;i++) 61 { 62 char s1[25],s2[25]; 63 long long p,q; 64 65 scanf("%s%s%lld%lld",s1,s2,&p,&q); 66 67 if (mmp[s1]) 68 { 69 v[mmp[s1]].push_back(node{p,q}); 70 } 71 else 72 { 73 mmp[s1] = ++cnt; 74 v[cnt].push_back(node{p,q}); 75 } 76 } 77 78 long long l = 0,r = 1e11; 79 80 while (r > l + 1) 81 { 82 long long mid = (l + r) >> 1; 83 84 if (meet(mid)) l = mid; 85 else r = mid; 86 } 87 88 while (meet(l+1)) l++; 89 90 printf("%lld\n",l); 91 } 92 93 return 0; 94 }
康复训练中~欢迎交流!