【动态规划】常见背包问题合集

本文详细介绍了背包问题的不同类型及其对应的解决方案,包括01背包、完全背包、多重背包、混合背包、二维背包及分组背包等,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01背包: 

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

转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]},可以优化只用一维数组.
代码如下: 

  1. for(int i=0;i<nPack;i++)  
  2.     for(int j=nMaxVolume;j>=w[i];j–)  
  3.         if(record[j-c[i]]+v[i]>record[j])  
  4.                 record[j]=record[j-c[i]]+v[i];  

完全背包:

如果物品不计个数,即每个物品有无穷多件的话,稍微改一下代码即可。 


  1. for(int i=0;i<nPack;i++)  
  2.     for(int j=w[i];j<=nMaxVolume;j++)  
  3.         if(record[j-c[i]]+v[i]>record[j])  
  4.                 record[j]=record[j-c[i]]+v[i];  


多重背包:

每个物品给出确定的件数,求可以得到的最大价值。 

  1. for(i=0;i<kind;i++)  
  2.     for(j=0;j<bag[i];j++)  
  3.         for(k=nManVolume;k>=v[i];k–)  
  4.             if(record[j-c[i]]+v[i]>record[j])  
  5.                 record[j]=record[j-c[i]]+v[i];  

优化版本:
  1. //0-1背包,代价为cost,获得的价值为weight  
  2. void ZeroOnePack(int cost,int weight)  
  3. {  
  4.     for(int i=nValue;i>=cost;i–)  
  5.       dp[i]=max(dp[i],dp[i-cost]+weight);  
  6. }  
  7. //完全背包,代价为cost,获得的价值为weight  
  8. void CompletePack(int cost,int weight)  
  9. {  
  10.     for(int i=cost;i<=nValue;i++)  
  11.       dp[i]=max(dp[i],dp[i-cost]+weight);  
  12. }  
  13. //多重背包  
  14. void MultiplePack(int cost,int weight,int amount)  
  15. {  
  16.     if(cost*amount>=nValue) CompletePack(cost,weight);  
  17.     else  
  18.     {  
  19.         int k=1;  
  20.         while(k<amount)  
  21.         {  
  22.             ZeroOnePack(k*cost,k*weight);  
  23.             amount-=k;  
  24.             k<<=1;  
  25.         }  
  26.         ZeroOnePack(amount*cost,amount*weight);  
  27.     }  
  28. }  


 

混合背包

01背包,完全背包,多重背包的混合体

  1. for(i=0;i<n;i++)  
  2. {  
  3.     if(第i件物品是01背包)  
  4.         ZeroOnePack(c[i],v[i]);  
  5.     else if(第i件物品是完全背包)  
  6.         CompletePack(c[i],v[i]);  
  7.     else if(第i件物品是多重背包)  
  8.         MultiplePack(c[i],v[i]);   
  9. }  
}

二维背包:

对于每件物品有两种不同费用,比如有n种物品,每种物品都有体积vi,重量wi,价值ti,限制体积最多为V,重量最多为W

增加了一维费用,只需要状态也增加一维即可。设f[i][x][y]表示前i件物品,付出两种代价分别为x和y时可以获得的最大价值。

f[i][x][y]=max{f[i-1][x][y],f[i-1][x-v[i]][y-w[i]]+t[i]} 

  1. for(i=0;i<n;i++)  
  2. {  
  3.     for(int x=V;x>=v[i];x–)  
  4.     {  
  5.         for(int y=W;y>=w[i];y–)  
  6.         {  
  7.             f[x][y]=max(f[x-v[i]][y-w[i]]+t[i],f[x][y]);      
  8.         }     
  9.     }     
  10. }  


分组背包:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,
最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

  1. for(int i=1;i<=n;i++)//有n组   
  2.     for(int j=V;j>=1;j–)//从后往前遍历   
  3.         for(int k=1;k<=m;k++)//第i组内的各个数据  
  4.             if(j-k>=0&&dp[j]<dp[j-cost[i][k]]+value[i][k])dp[j]=dp[j-cost[i][k]]+value[i][k];//cost[i][j]表示第i组第j个物品的花费,value[i][j]表示第i组第j个物品的价值   


需要注意的细节:

如果没有要求背包一定要装满,则record[i]初始化为0。如果要求一定要装满,则除了record[0]为0之外其他record[i]初始化为-INF。



转自:https://blog.youkuaiyun.com/Hemk340200600/article/details/64210235

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值