01背包 && 完全背包 && 多重背包 复习 (HDU 2602 1114 2191)

最近计划刷点dp的题目,先把以前做的背包复习一下。

 

01背包

有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

题目链接

题意:n个骨头,背包体积为v, 下面两行,第一行是骨头的价值,第二行是骨头的体积。

注意:有可能有体积为0,但是有价值的骨头。

初始化:要求恰好装满背包,那么在初始化时除了d[0]为0, 其它d[1..V]均设为-∞。

如果并没有要求必须把背包装满,而是只希望价值尽量大,初始化时应该将d[0..V]全部设为0。

 

二维代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define Max(a,b)((a)>(b)?(a):(b))
 5 using namespace std;
 6 const int maxn = 1000+10;
 7 int d[maxn][maxn], c[maxn], w[maxn];
 8 
 9 int main()
10 {
11     int t, n, v;
12     int i, j;
13     cin>>t;
14     while(t--)
15     {
16         cin>>n>>v;
17         for(i = 0; i <= n; i++)
18         d[i][0] = 0;
19         for(j = 0; j <= v; j++)
20         d[0][j] = 0;
21 
22         for(i = 1; i <= n; i++)
23         cin>>w[i];
24         for(i = 1; i <= n; i++)
25         cin>>c[i];
26         for(i = 1; i <= n; i++)
27         for(j = 0; j <= v; j++)
28         {
29             d[i][j] = d[i-1][j];
30             if(j >= c[i])
31             d[i][j] = Max(d[i-1][j], d[i-1][j-c[i]] + w[i]);
32         }
33         cout<<d[n][v]<<endl;
34     }
35     return 0;
36 }

 

一维代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define Max(a,b)((a)>(b)?(a):(b))
 5 using namespace std;
 6 const int maxn = 1000+10;
 7 int d[maxn], c[maxn], w[maxn];
 8 
 9 int main()
10 {
11     int t, n, v;
12     int i, j;
13     cin>>t;
14     while(t--)
15     {
16         cin>>n>>v;
17         memset(d, 0, sizeof(d));
18         for(i = 1; i <= n; i++)
19         cin>>w[i];
20         for(i = 1; i <= n; i++)
21         cin>>c[i];
22         for(i = 1; i <= n; i++)
23             for(j = v; j >= c[i]; j--)
24             d[j] = Max(d[j], d[j-c[i]] + w[i]);
25         cout<<d[v]<<endl;
26     }
27     return 0;
28 }

 

完全背包

有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。

求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

题目链接

题意:已知存钱罐装满钱前后的重量,相减就是背包的容量,给N种类型的硬币的价值和重量(数目无限),

求出把背包装满可以获得的最小的价值。

分析:完全背包变形。dp[0]=0, 其他的都初始化为无穷大,dp时,将max改为min。注意d[]和c[],p[]数组的大小是不一样的。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define Min(a,b)((a)>(b)?(b):(a))
 5 using namespace std;
 6 const int maxn = 500+10;
 7 const int INF = (1<<28);
 8 int d[10000+10], c[maxn], w[maxn];
 9 
10 int main()
11 {
12     int t, v, n;
13     int v1, v2, i, j;
14     cin>>t;
15     while(t--)
16     {
17        cin>>v1>>v2;
18        v = v2-v1;
19        cin>>n;
20        for(i = 1; i <= n; i++)
21         cin>>w[i]>>c[i];
22 
23         d[0] = 0;
24        for(i = 1; i <= v; i++)
25         d[i] = INF;
26        for(i = 1; i <= n; i++)
27        for(j = c[i]; j <= v; j++)
28        d[j] = Min(d[j], d[j-c[i]] + w[i]);
29        if(d[v] == INF)
30         cout<<"This is impossible."<<endl;
31        else
32        printf("The minimum amount of money in the piggy-bank is %d.\n", d[v]);
33     }
34     return 0;
35 }

 

 

 

多重背包

有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。

求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

题目链接

题意:n 经费的金额, m 大米的种类, 下面m行,每行三个数,代表 每袋的价格、重量、袋数。

思路:二进制优化。注意 d[],c[],w[] 数组要开的比给定的v值大一些,因为二进制优化以后数组会大很多。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define Max(a,b)((a)>(b)?(a):(b))
 5 using namespace std;
 6 const int maxn = 100+10;
 7 int d[maxn*10], c[maxn*10], w[maxn*10];
 8 
 9 int main()
10 {
11     int t, v, n, cnt;
12     int i, j, k;
13     int c1, w1, n1;
14     cin>>t;
15     while(t--)
16     {
17        cin>>v>>n;
18 
19        memset(d, 0, sizeof(d));
20        cnt = 1;
21        while(n--)
22        {
23            cin>>c1>>w1>>n1;
24            for(k = 1; k <= n1; k<<=1)
25            {
26                c[cnt] = k*c1;
27                w[cnt++] = k*w1;
28                n1 -= k;
29            }
30            if(n1 > 0)
31            {
32                c[cnt] = n1*c1;
33                w[cnt++] = n1*w1;
34            }
35        }
36         for(i = 1; i < cnt; i++)
37         for(j = v; j >= c[i]; j--)
38         d[j] = Max(d[j], d[j-c[i]] + w[i]);
39 
40         cout<<d[v]<<endl;
41     }
42     return 0;
43 }

 

 

 

 

 

 

posted @ 2014-05-24 00:40  水门  阅读(163)  评论(0)    收藏  举报