(01背包)HDU

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126


题意:给n个物品,和m块钱,输出最多物品个数和其方案数。


委屈:求出最多物品个数就是一个裸的01背包,但是同时求出方案数,难住了我。

想了半天,感觉可以一波dp求出来,但是又想不明白状态是怎么表示和转移的。

无奈就先写个dfs提交试一发,果断超时了。

最后无奈看了题解,只能说,01背包还是不会。

其实与其说01背包不会不如说动态规划不会,感觉好难。

感觉自己好lowbee啊。。

感觉碰到dp就萎了。

1、想不出状态转移方程

2、搞不清循环的顺序

3、定不了正确的边界

好垃圾啊我。。


分析:在dp上加一维,dp[][0]表示原本的背包,dp[][1]表示方案个数。

把每个物品的价值看成1。

当当前的物品选择取时:

如果总价值和不取一样多,说明两种不同的总花费得到了相同的价值,这个时候,方案数应该想加起来。

if (dp[j][0]==dp[j-cost[i]][0]+1)  
       dp[j][1]=dp[j-cost[i]][1]+dp[j][1];  

如果总价值比不取多,说明在原总价值的基础上产生了新的花费方案,但是这些方案继承于取前的方案,所以方案数不变。

1 else if (dp[j][0] < dp[j-cost[i]][0]+1)  {  
2      dp[j][0]=dp[j-cost[i]][0]+1;  
3      dp[j][1]=dp[j-cost[i]][1];  
4 } 

代码:

 1 #include <set>
 2 #include <map>
 3 #include <list>
 4 #include <cmath>
 5 #include <queue>
 6 #include <vector>
 7 #include <bitset>
 8 #include <string>
 9 #include <cctype>
10 #include <cstdio>
11 #include <cstring>
12 #include <cstdlib>
13 #include <iostream>
14 #include <algorithm>
15 
16 using namespace std;
17 
18 typedef long long ll;
19 typedef unsigned long long ull;
20 #define inf (0x3f3f3f3f)
21 #define lnf (0x3f3f3f3f3f3f3f3f)
22 #define eps (1e-8)
23 int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
24 
25 //--------------------------
26 
27 int t;
28 int cost[40];
29 int dp[510][2];
30 int n,m;
31 
32 void solve(){
33     scanf("%d",&t);
34     while(t--){
35         scanf("%d%d",&n,&m);
36         for(int i=0;i<n;i++){
37             scanf("%d",&cost[i]);
38         }
39         memset(dp,0,sizeof(dp));
40         for(int i=0;i<=m;i++){
41             dp[i][1]=1;
42         }
43         for(int i=0;i<n;i++){
44             for(int j=m;j>=cost[i];j--){
45                 if (dp[j][0]==dp[j-cost[i]][0]+1)  
46                     dp[j][1]=dp[j-cost[i]][1]+dp[j][1];  
47                 else if (dp[j][0] < dp[j-cost[i]][0]+1)  {  
48                     dp[j][0]=dp[j-cost[i]][0]+1;  
49                     dp[j][1]=dp[j-cost[i]][1];  
50                 } 
51             }
52         }
53         if(dp[m][0]==0)puts("Sorry, you can't buy anything.");
54         else printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.
",dp[m][1],dp[m][0]);
55     }    
56 }
57 
58 
59 
60 
61 
62 int main() {
63 
64 #ifndef ONLINE_JUDGE
65     freopen("in.txt", "r", stdin);
66     //freopen("out.txt", "w", stdout);
67 #endif
68     //iostream::sync_with_stdio(false);
69     solve();
70     return 0;
71 }
原文地址:https://www.cnblogs.com/tak-fate/p/5894753.html