背包浅学(1)关于对背包九讲的理解(未完待续ing)

1、 01 背包

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

(2)分析:

这是最简单的背包问题,一个物品只有放与不放两种情况

(3)状态转移方程:

定义F[ i , j ] 为前i个物品正好放入容量为j的背包中所获得的最大价值,  转移方程 F[ i, j ]  = max{F[ i -1, j ] , F[ i-1 , j - w[i] ] + v[i] (j<V)}

(4)代码

f[0][0] = 0;
 for (int i=1;i<=n;i++)
    for (int j=w[i];j<=V;j--){
        f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
    }

(5)空间优化

void ZeroOnePage(int C,int v);
for (int i=1;i<=n;i++)
    for (int j=V;j>=w;j--){
        f[j]=max(f[j],f[j-w]+v)
    }

  抽象成一个函数ZeroOnePage  

void ZeroOnePage(int C,int W)
{
   for (int j=V;j>=C;j--)
     F[j] = max(F[j],F[j-C]+W);
}

为什么第二重循环要逆向?  如果仍未正向,F[ i, j ]  = max{F[ i -1, j ] , F[ i-1 , j - w[i] ] + v[i] (j<V)},一维数组,f([i - 1])[j]已经被更改了

(6)初始化背包的细节问题

一般在这个地方有两种类型,一种题目要求恰好装满,另一种情况则没有要求,,,对于第一种情况的初始化,F[0 , 0] = 0 外,其余的都应该初始化为负无穷;对于第二种情况,全部初始为0便可


题目:见vijos 

 

2 、完全背包

(1)、题目
有N种物品和一个容量为V 的背包,每种物品都有无限件可用。放入第i种 物品的耗费的空间是Ci,得到的价值是Wi。求解:将哪些物品装入背包,可使 这些物品的耗费的空间总和不超过背包容量,且价值总和最大

(2)、分析

类似于0 1背包的,只是所不同的是物品可以取无限次,将0 1 背包取或不取两种状态变成不取或取0,1,2,3.。。。V/Ci件

仍按照0 1 背包的思路定义F[ i , j ] 为前i个物品正好放入容量为j的背包中所获得的最大价值,  转移方程 F[ i, j ]  = max{F[ i -1, j ] , F[ i-1 , j - k*w[i] ] + k*v[i] (k*w[i]<V)}

时间复杂度为 O(VN*V/Ci),复杂度过于大,需想办法优化

(3)优化1

若两件物品i,j 满足 Ci<=Cj && Wi>=Wj 则将物品j直接去掉,不用考虑。

另外针对背包也可以这么优化,做一次计数排序,计算出费用相同价值最高的物品

(4)转化为 0 1 背包求解

因为每件物品最多选择 [V/Ci]件,可以构造一个[V/Ci]件价值和费用的0 1 背包,但这样的时间复杂度不变,但不乏为一种想法

高效想法:考虑二进制,把物品拆成Ci*2^k,Wi*2^k,其中k是取遍Ci*2^k<V的所有负整数,,,时间复杂度为O(log(V/C)*N),不失为一种好的优化方式

(5)O(VN)的解法(加空间优化)

void CompletePake(int w,int v);
for (int i=1;i<=n;i++)
    for (int j=w[i];j<=V;j--){
        f[j]=max(f[j],f[j-w[i]]+v[i]);
    }
抽象成一个函数CompletePage

void CompletePage(int C,int W)
{
   for (int j=C;j<=V;j++)
      F[j] = max(Fj],F[j-C]+W);
}


可以思考一下完全背包为什么顺序循环?


3、多重背包

(1)、题目
有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费 的空间是Ci,价值是Wi。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。
(2)、分析:

与完全背包类似,只是把每个物品可选无限加了一个限定,转移方程F[i , j ]  = max{F[ i-1, j ] , F[i-1,j-k*w[i]]+k*v[i] | k<=Mi  }

(3)、优化

转化为 0 1 背包时间复杂度不变,暂不考虑,考虑二进制思想,把Mi件物品分成系数分别为2^1,2^2。。。2^k,Mi-2^k+1,(k为满足Mi-2^k+1>0的最大整数)

抽象成一个函数MultiplePage

void Multiple(int i,int C,int W,int M)
{
    if (C*M <= V)
    {
        CompletePage(C,W);
        return;
    }
    k = 1;
    while (k < M)
    {
        ZeroOnePage(k*C,k*W);
        M = M-k;
        k <<= 1;
    }
    ZeroOnePage(M*C,M*W);
}


(4)O(VN)的单调队列优化,未完待续ing



4、混合背包

(1)、问题
如果将前面1、2、3中的三种背包问题混合起来。也就是说,有的物品只可 以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取 的次数有一个上限(多重背包)。应该怎么求解呢

(2)、分析:

如果真正学会了前面三种背包,那混合背包完全就是前三种背包的一个联合体而已

for i = 1 to N 
    if 第i件物品属于01背包 
        ZeroOnePack(Ci,Wi) 
    else if 第i件物品属于完全背包 
        CompletePack(Ci,Wi) 
    else if 第i件物品属于多重背包 
        MultiplePack(Ci,Wi,Ni)


小结:(转自背包九讲)有人说,困难的题目都是由简单的题目叠加而来的。这句话是否公理暂且存之不论,但他在本讲中得到了充分的体现。本来0 1 背包,完全背包,多重

背包都不是难题,但是将他们简单的组合起来以后就得到了一道一定能吓到不少人的题目。但只要基础扎实,领会三种背包问题的思想,就可以把复杂的问题拆分成简单的问题

来解决(借此与大家共勉)





1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值