nyoj 311-完全背包 (动态规划, 完全背包)

311-完全背包


内存限制:64MB 时间限制:4000ms Special Judge: No
accepted:5 submit:7

题目描述:

直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO

输入描述:

第一行: N 表示有多少组测试数据(N<7)。 
接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0<M<=2000,0<V<=50000)
接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0<c<100000,0<w<100000)

输出描述:

对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)

样例输入:

2
1 5
2 2
2 5
2 2
5 1

样例输出:

NO
1

分析:
  1、完全背包问题是指每个元素可以不止选择一次的背包问题
  2、它要求所组成的结果必须把背包刚刚填满
  3、完全背包 = 初始化为负数 + 0-1背包(PS:判断状态方程对应dp的取值情况应该从小到大)
    ①、即就是for(int i = c; i<= V; ++ i) ...

核心代码:
  
1 while(m --)
2 {
3     scanf("%d%d", &v, %w);
4     for(int i = v; i <= V; ++ i)
5         dp[i] = max(dp[i], dp[i-v] + w);
6 }

 

C/C++代码实现(AC):

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <stack>
 7 #include <map>
 8 #include <queue>
 9 #include <set>
10 
11 using namespace std;
12 const int MAXN = 50010;
13 const int MAX = 0x3f3f3f3f;
14 
15 int main()
16 {
17 
18     int t, M, V, c, w, dp[MAXN];
19     scanf("%d", &t);
20     while(t --)
21     {
22         memset(dp, -MAX, sizeof(dp));
23         dp[0] = 0;
24         scanf("%d%d", &M, &V);
25         while(M --)
26         {
27             scanf("%d%d", &c, &w);
28             for(int i = c; i <= V; ++ i) // 从最小的面积考虑起走
29                 dp[i] = max(dp[i], dp[i-c] + w);
30         }
31         if(dp[V] < 0)
32             printf("NO\n");
33         else
34             printf("%d\n", dp[V]);
35     }
36     return 0;
37 }

 

posted @ 2018-05-28 23:22  GetcharZp  阅读(113)  评论(0编辑  收藏  举报