动态规划_01背包问题

时间:2022-01-01 15:08:15

        01背包,很经典的背包问题。为什么叫01背包呢?就是有或者没有,或者说一件物品装或者不装进背包。0表示不装,1表示装。好了,01背包问题就是有n个物品P1,P2,P3...Pn,对应的价值分别是V1,V2,V3...Vn。又有一个背包,容量为C。求该背包中能装下物品的最大价值。

        动态规划的关键点在于保存当前阶段的所有最优解集合,并使用这些最优解集合在下一阶段中构造新的最优解集合,如此迭代直到最后一个子阶段,这最后一个子阶段中的最优解就是全局最优解。那么我们怎么保证每次计算得到的结果都是当前阶段的最优解呢?这就要通过子问题的分解实现了,子问题的分解就是将问题分解成几个不同情况的子问题,要求这些子问题包含了父问题的所有可能解。那么在某一个求解阶段中,我们只需要的计算这几个子问题的解,并保存其中的最优解。

        01背包的子问题分解思想是,讨论是否将第n号物品放进背包(注意是特指“第n号物品,而不是第n件物品",这里必须强调一下,因为我刚开始看书时看出懂,为什么图片第二号后面都是3,明明可以放更大的数吗,后来才想明白,第n行就是针对第n号元素讨论)。不管放还是不放,我们要做的就是得到该子问题的优解。当然前提条件是背包能够放进这第n号物品,所以可以得到该子问题的最优解方程如下:

        1.当C<Wn时,f(n,c) = f(n-1,c),即因为根本就放不下,所以f(n,c)除了f(n-1,c)这种最优解外,再没有第二种选择了。

        2.当C>=Wn时,f(n,c) = Max{f(n-1,c-Wn)+Vn,f(n-1,c)},其中Max{}中的前者表示放第n号物品,后者表示不放。

        上面两式其实就是01背包问题的状态转移表达式。下面看一下图表例子,以及java实现的代码

动态规划_01背包问题

        代码:

package com.wly.algorithmbase.dailyproblem;

/**
* 用动态规划求解01背包问题
* 状态转移方程:
* f(i,j) = Max{f(i-1,j),f(i-1,j-Wi)+Vi},其中j>=Wi
* f(i,j) = f(i-1,j),当j < Wi时
* @author wly
*
*/
public class ZeroOnePackageProblem {

public static void main(String[] args) {
int[] values = {0,3,4,5,7};
int[] weights = {0,2,3,4,5};
int VOLUME = 9; //背包容量

int c[][] = new int[values.length][VOLUME+1]; //这里VOLUME+1,是为表示容积为0的情况

for(int i=0;i<values.length;i++) {
c[i][0] = 0;
}

for(int j=0;j<VOLUME;j++) {
c[0][j] = 0;
}



//使用动态规划填充"可行解表格"
for(int i=1;i<c.length;i++) { //注意i从事1开始的特指"1号物品",不是一个物品哦!
for(int j=1;j<c[0].length;j++) { //对背包容量的遍历
//填充行元素
if(j >= weights[i]) { //注意是>=,不是>
c[i][j] = Math.max(c[i-1][j], c[i-1][j-weights[i]] + values[i]);
} else {
c[i][j] = c[i-1][j]; //放不下当前遍历的物品,转移状态,子问题为容量j的背包放置前i-1个物品
}
}
}

printArray(c);
System.out.println();
System.out.println("最大价值:" + c[c.length-1][c[0].length-1]);
}

private static void printArray(int[][] array) {
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[0].length;j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
}

          运行结果:
0 0 0 0 0 0 0 0 0 0 
0 0 3 3 3 3 3 3 3 3
0 0 3 4 4 7 7 7 7 7
0 0 3 4 5 7 8 9 9 12
0 0 3 4 5 7 8 10 11 12

最大价值:12
          O啦~~~

       转载求保留出处:http://blog.csdn.net/u011638883/article/details/14526019

       谢谢!!