动态规划求解01背包相关的基本问题

来源:互联网 发布:数据标准化处理的方法 编辑:程序博客网 时间:2024/06/16 19:26

背包问题是经典问题,网上已经提供了很多优秀的解法,这里摘录动态规则的方法,同时顺便把背包相关的变形问题也一些阐述。

问题:

1. 经典背包问题:给定一个载重量为m,n个物品,其重量为wi,价值为vi,1<=i<=n,要求:把物品装入背包,并使包内物品价值最大。

2. 变形:要求装入的物品重量最大?(问题很简单,但请先别BS我)

3. 变形:要求装入的物品重量刚好等于背包的承重?换一种说法就是:N个数里挑出任意个数,使这些数的和等于某个值M。

4. 变形:N个数里挑出任意个数,使这些数的和最接近M,即和与M的差的绝对值最小。


问题1请参考:http://blog.csdn.net/livelylittlefish/article/details/2186206#

核心思想如下:

在0/1背包问题中,物体或者被装入背包,或者不被装入背包,只有两种选择。
                      
循环变量i,j意义:前i个物品能够装入载重量为j的背包中
(n+1)*(m+1)数组value意义:value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值
若w[i]>j,第i个物品不装入背包
否则,若w[i]<=j且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值(替换为第i个物品装入背包后的价值)


问题2:很简单。可以将这里的重量看成是问题1的价值。之所以写出来是为了方便分析问题4.

问题3:采用类似于问题1的方法,对N个数(无序),以N[i]表示第i个数。构造一个(N+1)行(M+1)列的矩阵(+1行与列是为了下标好计算)。

关键点:对于某个M=j。给定序列N[1~i],组成和为 j 的子集U中若包含N[i],则N[1~i-1]肯定能够组成和为j-N[i]。

如图所示,为了简单起见,令N个数正好是1到N递增(不需要是有序的,仅为举例方便),令M=6。

矩阵的值V[i][j]有三种表示方法:

1. Y。表示N[i] =  j。这样,由N[1~i]个数,和为j的一种挑法就是只挑出N[i]本身。

2. X。表示由N[1~i]个数构成和为j的集合中,任一集合都没有N[i] 。

3. 矩阵的另一个地址,表示N[i] 可以构成和为j的集合中的一个元素,而其它的元素需要到矩阵的另一个地址中继续寻找。


算法描述如下:

1. 若当前N[i]=j ,则V[i][j]标记为 “Y”;

2. 判断N[i]是否属于加和集合。需要看N[1~i-1]是否可以构成 j-N[i]。判断的方法就是对第j-N[i]列,从行号为i-1开始直到0,看是否有值不为 “X”。查找的结果有两种可能:

a. 没有,即全为X。表示N[i]不可能属于加和集合中的一分子,故把V[i][j]标记为 “X”;

b. 有。记录转转地址。


当遍历结束后。采用回溯可以得到所有构成的路径。这时,标记为“Y”的矩阵值即是路径回溯的终点。

N个数\M

0

1

2

3

4

5

6

0

Y

X

X

X

X

X

X

1

X

Y

X

X

X

X

X

2

X

X

Y

11

X

X

X

3

X

X

X

Y

11

22

23

4

X

X

X

X

Y

11

22

5

X

X

X

X

X

Y

11

举例分析:

初始化第0行与第0列。

看v[1][1],由于有N[1]=1,故标记为Y。

看v[2][3],考虑N[2]=2是否是构成和为3的一个元素,则需要看由元素集合N[1~i-1],是否可以构成j-N[i],即{1}是否可以构成和为1。从查找v[1][1]找到v[0][1],发现v[1][1]标记为Y,表示可以构成,所以v[2][3]记录地址{1,1}。

看v[3][6],同理,若N[3]=3能构成和为6的一个元素的话,就要求N[1~2]能构成和为3,查找发现v[2][3]的值不是“X”,表示上述假设成立,因此记录(2,3).


当遍历结束后,回溯寻找和为M的方法,这里M=6.

首先发现v[5][6],确定5,跳转到v[1][1],为Y,结束,集合为{1,5}. 同列往上继续走到v[0][1],为X,结束。

往上走到v[4][6], 确定4,跳转到v[2][2],为Y,结束,集合为{2,4}. 同列往上继续走到v[1][2]与v[0][2],皆为X,结束。

往上走到v[3][6],确定3,跳转到v[2][3],确定2,跳转到v[1][1],确定1,集合为{1,2,3}. 同列往上继续走到v[0][1],为X; 回退,发现v[1][3]也为X,结束。

往上走到v[1~2][6],都没有构成集合,结束。


这里为什么在找到一条路径后,还需要继续在同列往上走呢?这是为把所有组合都成找到,请自行分析M=7的情况,如果不往上走,将只能找到{2,5}与{3,4},而少一组{1,2,4}.而最后一组{1,2}又构成了3.


问题4:

运用问题2或3的解法可解。运用问题2来解比较快:假设背包最大承重为M,解一次问题2,即可得到加和小于M,且最接近M的的值,设为S。由于求的是绝对值最小,所以有可能可以找到加和大于M的解,而这个解必然属于背包大小为M+1到M+(M-S)-1 范围内,问题2的解。举例如下:假设M=6,求得S=3,目前的绝对值差为3,而如果正确的解是S>M的情况,那么该解必然属于背包大小为7到8当中的最优解。即,最坏情况下,给一个大小为8的包,能装满,则这时和的绝对值差为2,比原来优,而背包给的再大已经没有意义。

0 0
原创粉丝点击