标签:
依赖背包 事实上,这是一种树形DP,其特点是每个父节点都需要对它的各个儿子的属性进行一次DP以求得自己的相关属性。
fj打算去买一些东西,在那之前,他需要一些盒子去装他打算要买的不同的物品。每一个盒子有特定要装的东西(就是说如果他要买这些东西里的一个,他不得不先买一个盒子)。每一种物品都有自己的价值,现在FJ只有W元去购物,他打算用这些钱买价值最高的东西。
题意:有n件物品,对应有不同的价格和价值,这是典型的01背包。但现在有了一个限制,要买物品先买能装这件物品的特定的盒子,盒子的价值为0
代码理解得还不是太好,感觉这是一个“二重”的01背包。首先假设先买第i个盒子,对每个盒子里的物品进行一次01背包;然后对盒子再进行一次01背包,决策到底要不要买这个盒子
dp[i][j]表示前i个盒子有j元钱能获得的最大价值,则所求就是dp[n][total]
因为物品对盒子有了“依赖”,所以要先对dp赋值为-1,表示买不到盒子就更不可能装物品
代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <math.h> 5 #include <algorithm> 6 #include <iostream> 7 using namespace std; 8 9 #define N 100010 10 int dp[52][N]; 11 12 int main() 13 { 14 int n,total; 15 while(~scanf("%d%d",&n,&total)){ 16 memset(dp,-1,sizeof(dp)); //有依赖关系,要赋初值-1 17 memset(dp[0],0,sizeof(dp[0])); 18 for(int i=1;i<=n;i++){ 19 int box,m; 20 scanf("%d%d",&box,&m); 21 for(int j=box;j<=total;j++) 22 dp[i][j]=dp[i-1][j-box];//先让i层买盒子,因为盒子没有价值, 23 //所以直接等于上一层的花费+盒子钱 24 for(int j=0;j<m;j++){//在已花费盒子钱的基础上,此时再对dp[i]层做01背包, 25 //即i层一个盒子多种物品的最大价值 26 int c,w; 27 scanf("%d%d",&c,&w); 28 for(int k=total;k>=c;k--){ 29 if(dp[i][k-c]!=-1)//注意依赖背包有不可能的情况,这里即k买不到盒子和这个物品, 30 //不能装物品 31 dp[i][k]=max(dp[i][k],dp[i][k-c]+w);// 这里不能dp[i][k]=max(dp[i][j],dp[i][k-box-c]+w) 32 //因为已经买过盒子了,这个表达式代表一个盒子基础上一个物品带一个盒子 33 } 34 } 35 for(int j=0;j<=total;j++)//决策是否买第i个盒子 36 dp[i][j]=max(dp[i][j],dp[i-1][j]);//不要忘了考虑不选当前组的情况(不是必选) 37 } 38 printf("%d\n",dp[n][total]); 39 } 40 return 0; 41 }
参考:http://blog.csdn.net/yan_____/article/details/8539745
标签:
原文地址:http://www.cnblogs.com/wangmengmeng/p/4840840.html