动态规划第二讲——完全背包与多重背包问题

上一节,我们讨论了01背包问题,说明了*递归与分治法 与 动态规划DP的区别和联系,介绍了缓存的概念*。以下,我们用DC、DP、cache分别表示分治法、动态规划和缓存。本节,我们讨论01背包的另外两种形似——
完全背包和多重背包问题,分析DP问题的另外一些情况。

例一:完全背包问题

同样有n种价值和重量分别为weight[i] and value[i], 背包大小W。限制条件:每种物品数目是无限的。问:能挑选出来的总价值最大的物品组合总重量?

分析一:这里,我们无视数量有限这个条件,可以得到下列递归式:

dp[i+1][j] = max{dp[i][j-k*weight[i]] + k*value[i] | k>=0且k*weight[i]<=j}

下面,来实现这个动态规划(留给读者)。很不幸,我们发现这次的时间复杂度变成了三重循环,O(nW^2). 因为,此时将子问题组成原问题,需要的组合数目是W个而不是常数项。

分析二:

对上述递归式进行变形,可以变成dp[i+1][j] = max{dp[i][j], dp[i+1][j-w[i]] + v[i]};这样就可以将时间复杂度从O(nW^2)转化成O(nW).这个变形可以完全用数学化公式来实现,对应的物理意义:从前i+1号物品中选取j重的组合包含两种:1)不包含i+1号物品dp[i][j] 2) 包含至少一个i+1号物品dp[i+1][j-w[i]] + v[i].

优化2:DP数组的重复利用

另外,我们注意到,在在递推关系dp[i+1][j] = max{dp[i][j], dp[i+1][j-w[i]] + v[i]}中,dp[i+1][j]中,计算d[i+1][j]的时候仅仅用到了上一行左侧的数据,所有我们可以对数组进行重复利用,这样能够减少空间上的时间复杂度和程序执行时间(程序具有更好的局部性):

dp[j] = max(dp[j], dp[j-w[i]] + v[i]);

例二:01背包问题之二

和第一节中同样的背包问题,我们增加如下的限制条件:

1< n< 100

1< wi < 10^7

1< vi < 100

1< W < 10^9

此时,显然O(nW)的算法时间复杂度就不是能够接受的了;此时我们需要对子问题的定义作出变形—— dp[i][j]原来表示前i号物品选取重量不超过j的组合能产生的最大值, 现在dp[i][j]:前i号物选取价值为j的组合占用的最小重量,最后取出dp[n][j]<=W 的最大的j即可。

此时:初始化dp[0][0]=0;dp[0][j]=INF

dp[i+1][j] = min(dp[i][j], dp[i][j - v[i]] + w[i]);

例子三:多重部分和问题

有n种大小不同的数字ai,每种mi个,是否可以从中选取组合,使得它们的和是K

限制条件:

n<100;ai, mi<10^5; K<10^5

分析一:套用完全背包问题

dp[i][j]:前i号数字是否能组成和为j的组合;这样得到递推关系dp[i+1][j] ||= dp[i][j-k*a[i]];

时间复杂度O(nKK);这个时间复杂度并不好;一般来说DP的子问题不应该用来存储bool的结果,这意味着我们损失了更多的信息。

我们仔细来分析一下时间复杂度主要耗费在什么地方,先看没有优化之前的代码

for (i = 0; i < n; ++i){

for (j = 0; j <=K; ++j){

for (k = 0; k < m[i] && k*a[i] <=j ; ++k){

dp[i+1][j] |= dp[i][j-k*a[i]];

}

}

}

分析2:“ 优化成最优子结构”  

显然,for k 部分的循环,直观感觉是有冗余。分类一下,如果能从前i中数字选择出K和,a[i]可能被选取1次以上或者没有被选取

如果a[i]没有被选取,那么意味着dp[i][j]=true;

如果a[i]被选取了1次以上,意味着dp[i+1][j-a[i]]=true;

也就是说,dp[i+1][j]本来是和dp[i][j-k*a[i]]这么多子问题相关的;但是现在被转化成两个子问题dp[i][j] 和dp[i+1][j-a[i]],是不是很神奇?很显然,在这里,我们通过分治法对子问题进行了合并。

进一步,如果定义dp[i+1][j]:前i种数加和得到j的时候,a[i]剩余的个数,则有

dp[i+1][j]={

m[i]; if(dp[i][j]>=0)

dp[i+1][j-a[i]] -1;(j-a[i]>=0 && dp[i+1][j-a[i]]>=0)

-1;(otherwise)

}

总结:在计数原理中,这种 子问题分类合并的思想和方法非常常用!

时间: 2024-12-13 03:17:33

动态规划第二讲——完全背包与多重背包问题的相关文章

动态规划——背包问题python实现(01背包、完全背包、多重背包)

目录 01背包问题 完全背包问题 多重背包问题 参考: 背包九讲--哔哩哔哩 背包九讲 01背包问题 01背包问题 描述: 有N件物品和一个容量为V的背包. 第i件物品的体积是vi,价值是wi. 求解将哪些物品装入背包,可使这些物品的总体积不超过背包流量,且总价值最大. 二维动态规划 f[i][j] 表示只看前i个物品,总体积是j的情况下,总价值最大是多少. result = max(f[n][0~V]) f[i][j]: 不选第i个物品:f[i][j] = f[i-1][j]; 选第i个物品:

多重背包问题(来源:背包九讲)

问题: 有N种物品和一个容量为V的背包.第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 基本算法: 这题目和全然背包问题非常类似.主要的方程仅仅需将全然背包问题的方程稍微一改就可以,由于对于第i种物品有n[i]+1种策略:取0件,取1件--取n[i]件.令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程:f[i][v]=max{f[i-1][v-k*c[i]]+k*w

第二讲 完全背包问题(对背包九讲的学习)

学习自:背包九讲 题目 有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 基本思路: 完全背包和01背包的区别是一个物品可以被拿无限次,我们之前01背包是拿或者不拿的max,比较,然后我们处理完全背包的时候每个物品拿多少次就好了 每个物品最优拿法=max(不拿,拿一个,拿两个,...,拿n个),抛出个问题,n难道是无限吗?显然不是,大前提是背包总空间或者说处理到第i个物

有关货币问题的动态规划题目--有关01背包,完全背包,多重背包

背包dp:参考背包九讲以及给出一些题目 01背包 (先枚举物品,再逆序枚举容量) 给定n件物品和一个容量为V的背包,每件物品的体积是w[i],价值是va[i](1<=i<=n),求在不超过背包的容量的情况下,怎么选择装这些物品使得得到的价值最大? 例如:有5件物品,体积分别是{2,2,6,5,4},价值分别是{6,3,5,4,6} 递归式:F(i,v)=max(F(i-1,v), F(i-1,v-w[i])+va[i]),其中F(i,v)表示把前i种物品恰放入背包容量为v时取得的最大价值 把这

背包问题(01背包,完全背包,多重背包)

转自:http://www.cnblogs.com/daoluanxiaozi/archive/2012/05/06/2486105.html 背包问题,经典有背包九讲. 01背包 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑士:"我要买道具!" 地精商人:"我们这里有三种道具,血瓶150块一个,魔法药200块一个,无敌药水350块一个." 死亡骑士

【动态规划】多重背包问题

说明 前面已经介绍完了01背包和完全背包,今天介绍最后一种背包问题--多重背包. 这个背包,听起来就很麻烦的样子.别慌,只要你理解了前面的两种背包问题,拿下多重背包简直小菜一碟. 如果没有看过前两篇01背包和完全背包的文章,强烈建议先阅读一下,因为本文跟前两篇文章关联性很强. 多重背包 有N种物品和一个容量为T的背包,第i种物品最多有M[i]件可用,价值为P[i],体积为V[i],求解:选哪些物品放入背包,可以使得这些物品的价值最大,并且体积总和不超过背包容量. 对比一下完全背包,其实只是多了一

【动态规划/多重背包问题】POJ1014-Dividing

多重背包问题的优化版来做,详见之前的动态规划读书笔记. dp[i][j]表示前i中数加得到j时第i种数最多剩余几个(不能加和得到i的情况下为-1)递推式为: dp[i][j]=mi(dp[i-1][j]≥0,即前i-1种数就能达到数字j) =-1(j<ai 或者 dp[i][j-ai]≤0,即再加上一个第i种数也无法达到j 或者 当前和小于当前数) =dp[i][j-ai]-1(可以达到的情况) #include<iostream> #include<cstdio> #inc

动态规划-多重背包问题

0-1背包问题 完全背包问题 多重背包问题是0-1背包问题和完全背包问题的综合体,可以描述如下:从n种物品向容积为V的背包装入,其中每种物品的体积为w,价值为v,数量为k,问装入的最大价值总和? 我们知道0-1背包问题是背包问题的基础,所以在解决多重背包问题的时候,要将多重背包向0-1背包上进行转换.在多重背包问题中,每种物品有k个,可以将每种物品看作k种,这样就可以使用0-1背包的算法.但是,这样会增加数据的规模.因为该算法的时间复杂度为O(V*∑ni=1ki),所以要降低每种物品的数量ki.

背包之01背包、完全背包、多重背包详解

首先说下动态规划,动态规划这东西就和递归一样,只能找局部关系,若想全部列出来,是很难的,比如汉诺塔.你可以说先把除最后一层的其他所有层都移动到2,再把最后一层移动到3,最后再把其余的从2移动到3,这是一个直观的关系,但是想列举出来是很难的,也许当层数n=3时还可以模拟下,再大一些就不可能了,所以,诸如递归,动态规划之类的,不能细想,只能找局部关系. 1.汉诺塔图片 (引至杭电课件:DP最关键的就是状态,在DP时用到的数组时,也就是存储的每个状态的最优值,也就是记忆化搜索) 要了解背包,首先得清楚