【NOIP2006】金明的预算方案

又是一道经典的背包问题,在洛谷上的链接:https://www.luogu.org/problemnew/show/P1064


 

和01背包不同的是,物品之间存在依赖关系,要想购买附件就必须购买主件,所以就可以这样想,从{主件,主件+附件1,主件+附件2,主件+附件1+附件2}中选择一个物品放入背包,然后使得总价值最大。这样只需要处理主件,处理每个主件时的状态转移方程修改一下就可以了,详见代码。同样的将其类比成01背包后,也可以将空间复杂度降到O(n)。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int maxn = 3205, maxm = 65;
 7 
 8 int v[maxm][3], p[maxm][3], dp[maxn];
 9 
10 int main() {
11     int n, m;
12     scanf("%d%d", &n, &m);
13     n /= 10;
14     for (int i = 1; i <= m; ++i) {
15         int a, b, c;
16         scanf("%d%d%d", &a, &b, &c);
17         a /= 10;
18         if (!c) v[i][0] = a, p[i][0] = b * v[i][0];
19         else {
20             if (v[c][1]) v[c][2] = a, p[c][2] = b * v[c][2];
21             else v[c][1] = a, p[c][1] = b * v[c][1];
22         }
23     }
24     for (int i = 1; i <= m; ++i) if (v[i][0])
25         for (int j = n; j >= v[i][0]; --j) {
26             dp[j] = max(dp[j], dp[j - v[i][0]] + p[i][0]);
27             if (j >= v[i][0] + v[i][1]) dp[j] = max(dp[j], dp[j - v[i][0] - v[i][1]] + p[i][0] + p[i][1]);
28             if (j >= v[i][0] + v[i][2]) dp[j] = max(dp[j], dp[j - v[i][0] - v[i][2]] + p[i][0] + p[i][2]);
29             if (j >= v[i][0] + v[i][1] + v[i][2]) dp[j] = max(dp[j], dp[j - v[i][0] - v[i][1] - v[i][2]] + p[i][0] + p[i][1] + p[i][2]);
30         }
31     printf("%d", dp[n] * 10);
32     return 0;
33 }
AC代码

 

posted @ 2018-09-05 10:23  Mr^Kevin  阅读(133)  评论(0编辑  收藏  举报