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

",kase++,ans);
41     }
42     return 0;
43 }
Great Number
 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
", max(v, 1000000ll));
40         if(v > q) {
41             //printf("t : %lld
", v);
42             t = (v - q) / app[2].s + 1ll;
43             v -= t * app[2].s;
44         }
45         //printf("%lld
", 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
", 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,因为先考虑的是第一个,所以还是应该枚举。这样想,已经在两个题目上验证是错误的,应该放弃这种思想了。。。

原文地址:https://www.cnblogs.com/ACMERY/p/4440372.html