首页 > 代码库 > (01背包)HDU - 2126 Buy the souvenirs

(01背包)HDU - 2126 Buy the souvenirs

原题链接: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.\n",dp[m][1],dp[m][0]);55     }    56 }57 58 59 60 61 62 int main() {63 64 #ifndef ONLINE_JUDGE65     freopen("in.txt", "r", stdin);66     //freopen("out.txt", "w", stdout);67 #endif68     //iostream::sync_with_stdio(false);69     solve();70     return 0;71 }

 

(01背包)HDU - 2126 Buy the souvenirs