理论介绍
动态规划(Dynamic Programming, DP)算法的核心思想为:将大问题划分成小问题进行解决,从而一步步获取最优解的处理算法。
动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治算法不同的是,适合于用动态规划求解的问题,经分解得到的子问题往往不是相互独立的(即下一子阶段的求解是建立在上一子阶段的解的基础之上,进行进一步的求解)。动态规划算法可以通过填表的方式来逐步推进,得到最优解。
实际问题:背包问题
问题:有一个背包,容量为4,现有如下物品
要求:
(1)要求达到的目标为装入背包的总价值最大,并且重量不能超出容量;
(2)要求装入的物品不能重复。
分析:
(1)背包问题主要是指一个给定容量的背包、若干具有一定价值和重量的物品,如何选择物品放入背包使得物品的价值最大。背包问题又可分为:01背包和完全背包(完全背包是指每种物品都有无限件可用)。
(2)上述问题属于01背包,即每件物品最多放一个。
(3)动态规划算法解决此类问题的主要思想为:每次遍历到第i个物品,根据w[i]和v[i]来确定是否需要将该物品放入背包中。即对于给定的n个物品,设置v[i]、w[i]分别表示第i个物品的价值和重量,C为背包的容量;令v[i][j]表示在前i个物品中能够装入容量为j的背包中的最大价值。伪代码如下:
1) v[i][0]=v[0][j]=0; //表示填入表的第一行和第一列是0
2)当w[j]>j时,v[i][j]=v[i-1][j] //当准备加入新增的物品的容量大于当前背包的容量时,就直接使用上个单元格的装入策略
3)当j>=w[i]时:v[i][j]=max{v[i-1][j],v[i]+v[i-1][j-w[i]]} //当准备加入的新增物品的容量小于等于当前背包的容量
代码实现(Java)
package com.zq.dp;
public class DP_01 {
public static void main(String[] args) {
int[] w= {1,4,3};//物品的重量
int[] val= {1500,3000,2000};//物品的价值
int c=4;//背包的容量
int n=val.length;//物品的个数
int[][] v=new int[n+1][c+1];//表示前i个物品中能够装入容量为j的背包中的最大价值
//初始化第一行和第一列为0
for(int i=0;i<v.length;i++) {
v[i][0]=0;
}
for(int i=0;i<v[0].length;i++) {
v[0][i]=0;
}
//DP算法解决01背包问题
for(int i=1;i<v.length;i++) {
for(int j=1;j<v[0].length;j++) {
if (w[i-1]>j) {
v[i][j]=v[i-1][j];
}else {
v[i][j]=Math.max(v[i-1][j], val[i-1]+v[i-1][j-w[i-1]]);
}
}
}
System.out.print("最大价值为:"+v[n][c]);
}
}