10年省赛-Greatest Number (二分+暴力) + 12年省赛-Pick apples(DP) + UVA 12325(暴力-2次枚举)
题意:给你n个数,在里面取4个数,可以重复取数,使和不超过M,求能得到的最大的数是多少;
思路:比赛时,和之前的一个题目很像,一直以为是体积为4(最多选择四次)的完全背包,结果并不是,两两求和,然后二分枚举;
完全背包是固定的体积,然后尽量使得装下的重量最大;
这个题目是固定的体积,但求在不超过该重量的情况下能得到的最大值。
至于为啥不是完全背包到现在还找到一个反例,以后再修改;
不过看到一共选择四次的时候,就应该想到是暴力。。。
比较相似的一个题目,12年的省赛题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2408
那个是10的8次方,也是优化之后才能背包,将10的6次方的那部分先减掉,因为它是不限制取的次数的
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define N 10010 4 #define repu(i,a,b) for(int i=a;i<b;i++) 5 #define ll long long 6 int c[N],a[N]; 7 int main() 8 { 9 int n,m,b,kase = 1,ok = 0; 10 while(scanf("%d%d",&n,&m)&&n&&m) 11 { 12 vector<int> s; 13 s.clear(); 14 repu(i,0,n) 15 scanf("%d",&a[i]),s.push_back(a[i]); 16 repu(i,0,n) 17 { 18 repu(j,i,n) 19 if(a[i]+a[j] <= m) 20 s.push_back(a[i]+a[j]); 21 } 22 sort(s.begin(),s.end()); 23 int ans = 0; 24 repu(i,0,s.size()) 25 { 26 int st = i,ed = s.size() - 1; 27 while(st <= ed) 28 { 29 int mid = (st + ed) /2; 30 if(s[mid] + s[i] > m) 31 ed = mid -1; 32 else 33 { 34 if(s[i] + s[mid] > ans) 35 ans = s[i] + s[mid]; 36 st = mid + 1; 37 } 38 } 39 } 40 printf("Case %d: %d\n\n",kase++,ans); 41 } 42 return 0; 43 }
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <vector> 6 #include <algorithm> 7 using namespace std; 8 #define N 1000005 9 #define ll long long 10 11 struct App 12 { 13 ll s, p; 14 double k; 15 bool operator < (const App& rhs) const 16 { 17 return k < rhs.k; 18 } 19 } app[5]; 20 21 double d[N]; 22 int main() 23 { 24 int T; 25 scanf("%d", &T); 26 ll v; 27 ll q = 1000000; 28 for(int cases = 1; cases <= T; cases++) 29 { 30 memset(d, 0, sizeof(d)); 31 for(int i = 0; i < 3; i++) { 32 scanf("%lld%lld", &app[i].s, &app[i].p); 33 app[i].k = (double)app[i].p / (double)app[i].s; 34 } 35 scanf("%lld", &v); 36 sort(app, app + 3); 37 38 ll t = 0; 39 //printf("t : %lld\n", max(v, 1000000ll)); 40 if(v > q) { 41 //printf("t : %lld\n", v); 42 t = (v - q) / app[2].s + 1ll; 43 v -= t * app[2].s; 44 } 45 //printf("%lld\n", app[2].s); 46 for(int i = 0; i <= v; i++) 47 for(int j = 0; j < 3; j++) 48 if(i - app[j].s >= 0) 49 d[i] = max((double)d[i - app[j].s] + (double)app[j].p, d[i]); 50 51 printf("Case %d: %.0lf\n", cases, d[v] + (double)t * (double)app[2].p); 52 } 53 return 0; 54 }
UVA 题意:给固定体积,告诉你两种物品的体积,以及他们的价值,求最多能装的价值是多大;
看似像背包,但是可以暴力做,2次枚举同时,i个s1,i个s2,同时比较,保留大的,i循环100000就够了
误解:记得之前做过,队友说看比例,即第一个物体和第二个物体比较性价比,谁的高先留谁,装不下了再考虑第二个物体,之前我很赞同,现在有反例了:9 2 5 3 7(总体积,第一物体体积,价值,第二物体体积,价值)这组样例正确答案是21,但是按照上边的思路得出的是20,因为先考虑的是第一个,所以还是应该枚举。这样想,已经在两个题目上验证是错误的,应该放弃这种思想了。。。
人生就像心电图,想要一帆风顺,除非game-over