有趣背包问题

其实就是背包问题的一种应用,至于为什么起这么个名字,可以去问问神犇zhhx。。。

问题描述和01背包几乎一样,你有m元钱,有n个物品可供选择,每个物品都有各自的花费c和价值v,而且每件物品只可以选择一次,问在花费不超过m元的条件下,最大价值是多少。

嗯,就是和普通的01背包一样,不同之处在于数据范围,m,c<=10^9,n<=100,1<=v<=5。如果还和普通的背包一样,设dp[i][j]表示考虑完第i件物品,花费为j元的最大价值,显然是行不通的。

我们发现花费取值范围太大,而价值取值范围较小,可以交换一下状态和最优值,设dp[i][j]表示考虑完第i件物品,价值为j元时的最小花费,那么满足dp[i][j]<=m的最大的j就是答案。

然后就和普通的01背包没啥区别了,该滚动数组就滚动。

附一道题,可以考虑用这种方法做,NOIP2005普及组 采药:https://www.luogu.org/problemnew/show/P1048

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxv = 1e4 + 5;
 8 
 9 int dp[maxv];
10 
11 int main() {
12     int m, n, c, v, mv = 10000, ans = 0;
13     scanf("%d%d", &m, &n);
14     memset(dp, 0x3f3f3f3f, sizeof(dp));
15     dp[0] = 0;
16     for (int i = 1; i <= n; ++i) {
17         scanf("%d%d", &c, &v);
18         for (int j = mv; j >= v; --j) {
19             dp[j] = min(dp[j], dp[j - v] + c);
20             if (i == n && dp[j] <= m) ans = max(ans, j);
21         }
22     }
23     printf("%d", ans);
24     return 0;
25 }
AC代码

 

posted @ 2018-11-02 15:05  Mr^Kevin  阅读(115)  评论(0编辑  收藏  举报