您的位置:首页 > 其它

关于背包DP

2022-05-09 17:30 176 查看

今天在AKWING上学了点背包基础,简单记录一下:

首先,啥是背包问题???

简单举个例子,现在你是一个小偷,有一个包用来装你偷的东西,这个包的容量是有限的,假设你知道每件物品的价值和所占体积,你现在要决定要装走一些物品,使带走的物品价值最高。

这就是所谓的01背包问题,就是需要考虑权重的求最优解DP问题。

那这道题的思路是什么呢?

其实跟一般的DP相似(在不考虑优化的基础上),就是考虑当前状态的取舍来进行状态转移,(对于任意一个物品,你有两种选择,要么选(对应1),要么不选(对应0)),从而得到问题的最优解

针对DP问题,套上一般思路进行求解:

首先设定变量,一个二维数组 f[i][j] 代表只考虑 前 i 个物品,体积不超过 j 的状态的最大值(就是最大获利)

再建两个数组,v[i]和w[i],分别表示第i个物品的体积和价值

那还有就是状态计算,像原来一样,我们还是把状态分为两部分来考虑,一是选取第 i 个物品是的最大值,因为不选第 i 个,所以也就是从前 i-1 个物品中选取呗,那就是说: f[i][j] = f[i-1][j]

第二种情况就是选第 i 个物品,那就是前面 i-1个物品的选择最大值,加上第i个物品的最大值,也就是:f[i][j] = f[i-1][j-vi] + w[i]

还有就是初始化,f[0][i]=0,也就可以省略了

还可以改成一维数组:(滚动数组)

如果只用到了 i 和 i-1,那就可直接改成一维的

 

 

完全背包问题:

与01背包相似,区别就在于01背包每件物品最多只能选一次,而完全背包问题中的每个物品都有无数件

状态表示:依旧是所有只考虑前 i 个物品,且总体积不大于 j 的所有选法

状态计算:将其分为若干组,第i个物品选0个,选1个,选2个。。。选k个

选0个:f[i][j]=f[i][j-1]

其他的:1.去掉n个物品i

2求max,3.再加回来n个物品i的值。

即:f[i,j]=f[i-1,j-v[i]*n]+w[i]*n

f[i,j]=max(f[i-1,j],f[i-1,j-v[i]*1]+w[i]*1,f[i-1,j-v[i]*2]+w[i]*2,f[i-1,j-v[i]*3]+w[i]*3+......+f[i-1,j-v[i]*n]+w[i]*n)

f[i,j-v[i]]=max(f[i-1,j-v[i]*1]+w[i]*1,f[i-1,j-v[i]*2]+w[i]*2,f[i-1,j-v[i]*3]+w[i]*3+......+f[i-1,j-v[i]*n]+w[i]*n)

所以:f[i,j]=max(f[i-1,j] , f[i-1,j-v[i]]+w[i] ],直接少了一层枚举n的循环。

 

多重背包问题:(有有限数量的件数)

状态表示与原来一样

状态计算也与完全背包差不多:(设s[i]为第i个物品的数量)

f[i,j]=max(f[i-1,j],f[i-1,j-v[i]*1]+w[i]*1,f[i-1,j-v[i]*2]+w[i]*2,f[i-1,j-v[i]*3]+w[i]*3+......+f[i-1,j-v[i]*s[i]]+w[i]*s[i])

f[i,j-v[i]]=max(f[i-1,j-v[i]*1]+w[i]*1,f[i-1,j-v[i]*2]+w[i]*2,f[i-1,j-v[i]*3]+w[i]*3+......+f[i-1,j-v[i]*(s[i]+1)]+w[i]*(s[i]+1))

多了一项s[i]+1,无法和完全背包使用一样的优化方法

转换方法:二进制转换

比如说有1023个物品i

将其划分为若干组:1,2,4,8,16,32,64,128,256,512

再比如有200个物品i

将其划分成1,2,4,8,32,64,73

此时从0到s[i]之间任意的数都能用他们相加表示出来:

 

分组背包问题:

有若干组,每组里有若干件物品,要求每组最多选一个,使得价值最大且不超过背包限制

状态表示:只从前i组物品中选,且总体积不大于j的所有选法最大值

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: