【海亮DAY12(二)】背包的补充一


专辑:海亮集训-动态规划-背包


分三次更新


更新提示:第二次更新


背包主要分为以下几种:

1、01背包问题
2、完全背包问题
3、多重背包问题
4、混合三种背包问题
5、二维费用的背包问题
6、分组的背包问题
7、有依赖的背包问题
8、背包问题问法的变化

第二次更新主要讲解前四种背包


一、01背包

题目描述:有N 件物品和一个容量为V 的背包。放入第i 件物品耗费的空间是ci,得到的价值是wi。求解将哪些物品装入背包可使价值总和最大。

分析:用子问题定义状态:即f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。
对于每一种状态,都有两种情况,一种是取,一种是不取。便可以得到以下方程:

f [ i ] [ j ] = m a x { f [ i − 1 ] [ j ] , 不取当前物品 f [ i − 1 ] [ j − w [ i ] ] + c [ i ] , 选取当前物品 ( w [ i ] 为 体 积 , c [ i ] 为 价 值 ) f[i][j] =max \begin{cases} f[i-1][j], & \text{不取当前物品} \\ f[i-1][j-w[i]]+c[i], & \text{选取当前物品}(w[i]为体积,c[i]为价值) \end{cases} f[i][j]=max{f[i1][j],f[i1][jw[i]]+c[i],不取当前物品选取当前物品(w[i]c[i])

放一段主要代码:

for (int i=1;i<=n;i++) 
      for (int j=m;j>=c[i];j--)
        dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
我们接着思考:这样遇到大数据时会不会MLE?
如何优化时间复杂度?
◆第i次状态只与i − 1 有关
◆ f [j] 表示容量为j 的背包可以获得的最大值。
◆ 倒序求解,为保证状态f [i][j] 可以取到f [i − 1][j − ci]

代码如下:

for (int i=1;i<=n;i++) 
      for (int j=m;j>=c[i];j--)
        dp[j]=max(dp[j],dp[j-c[i]]+w[i]);

二、完全背包

题目描述:有N 件物品和一个容量为V 的背包,每件物品都有无限件。放入第i 件物品耗费的空间是ci,得到的价值是wi。求解将哪些物品装入背包可使价值总和最大。

分析:如果仍然按照解01背包时的思路,总复杂度为: O ( N V ∑ i = 0 n v / c [ i ] ) O(NV\sum_{i=0}^n v/c[i]) O(NVi=0nv/c[i])
考虑O(NV)算法
◆ 01背包倒叙计算是为保证每种物品只能取一次,而完全背包的特点恰是每种物品可选无限件。
◆ 顺序求解,在考虑“加选一件第i 种物品”这种策略时,正需要一个可能已选入第i 种物品的子结果f [i][j − ci]。

代码如下:

    for (int i=1;i<=n;i++) 
      for (int j=c[i];j<=m;j++)
        dp[j]=max(dp[j],dp[j-c[i]]+w[i]);

三、多重背包

题目描述:有N 件物品和一个容量为V 的背包,第i 件物品都有ni 件。放入第i 件物品耗费的空间是ci,得到的价值是wi。求解将哪些物品装入背包可使价值总和最大。

#####分析:解法与完全背包类似。略微调整,注意对于第i 种物品有ni + 1 种策略。枚举第i 件物品的件数k。
f [ i ] [ j ] = m a x { f [ i − 1 ] [ j − k × c i ] + k × w i , 0≤k≤n[i] f [ i ] [ j ] f[i][j] =max \begin{cases} f [i − 1][j − k × ci] + k × wi, &amp; \text{0≤k≤n[i]} \\ f[i][j] \end{cases} f[i][j]=max{f[i1][jk×ci]+k×wi,f[i][j]0≤k≤n[i]

但是我们并不能满足于暴力,我们要想优化的方法。
我们利用二进制优化

把一个数n拆分成几个2的次方数的和,能用这些数组成n范围内的任意一个数
例如12=1+2+4+5
1=001
2=010
4=100
5=101
用这些数进行加法,根据二进制,能够组成在n范围内的任意数,这便是二进制优化。
二进制优化完之后,变可以将优化完的数做一遍01背包得到最优解。

这里给一道多重背包的例题:

逃亡的准备

题目描述:在《Harry Potter and the Deathly Hallows》中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品,现在给出该种物品的数量、体积、价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常地感谢你。

分析:这道题是裸的多重背包,不再多分析,具体看代码。

那么代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,v;
int m[1000001]={};//数量
int w[1000001]={};//体积
int c[1000001]={};//价值
int ww[1000001]={};//分解后体积 
int vv[1000001]={};//分解后价值 
int tot=0;
int main(){
    scanf("%d %d",&n,&v);
	for (int i=1;i<=n;i++){
	    scanf("%d %d %d",&m[i],&w[i],&c[i]);
	    int tmp=1;
	    while (m[i]-tmp>=0){//二进制分解
		    m[i]-=tmp;
		    ww[++tot]=w[i]*tmp;//分解后存储体积
		    vv[tot]=c[i]*tmp;//分解后存储价值
		    tmp*=2;
		}
		if (m[i]>0) ww[++tot]=w[i]*m[i],vv[tot]=c[i]*m[i]; //如果还有,就存储剩余的
	}
	int dp[1000001]={};
//	cout<<tot<<endl;
	for (int i=1;i<=tot;i++)
	  for (int j=v;j>=ww[i];j--)
	    dp[j]=max(dp[j],dp[j-ww[i]]+vv[i]);//做一遍01背包
	cout<<dp[v];
	return 0;
} 


四、混合三种背包

混合三种背包就是混合上面的三种背包,没什么好讲的
混合三种背包有以下模板

for (int i=1;i<N;i++){

        if (物品属于0/1背包)

          //0/1背包解法

     }

   else if (物品属于完全背包)

        //完全背包解法

     else if (物品属于多重背包)

        //多重背包解法

这时第二次更新的四种背包
接下来的几种会在下一次更新中写

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值