动态规划算法(Dynamic Programming)算法也是将大问题划分为小问题进行解决,与分治算法类似,但适用于动态规划求解的问题,经分解得到子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。动态规划可以通过填表的方式来逐步推进,得到最优解。这儿用背包问题演示一次。
背包问题主要是指一个给定容量的背包、若干具有一定价值和重量的物品,如何选择物品放入背包使物品的价值最大。其中又分为01背包和完全背包(01背包即每个物品最多放一个;完全背包指的是每种物品都有无限件可用。无限背包可以转化为01背包)
public class KnapsackProblem {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] w = { 1, 4, 3 };// 物品的重量
int[] val = { 1500, 3000, 2000 };// 物品的价值
int m = 4;// 背包的容量
int n = val.length;// 物品的个数
// 为了记录放入商品的情况,我们定一个二维数组
int[][] path = new int[n + 1][m + 1];
// 创建二维数组
// v[i][j]表示在前i个物品中能装入容量为j的背包中的最大价值
int[][] v = new int[n + 1][m + 1];
// 初始化第一行和第一列,在本程序中可以不去处理,因为默认为0
for (int i = 0; i < v.length; i++) {
v[i][0] = 0;// 将第一列设置为0
}
for (int i = 0; i < v[0].length; i++) {
v[0][i] = 0;// 将第一行设置为0
}
for (int i = 1; i < v.length; i++) {// 不处理第一行
for (int j = 1; j < v[0].length; j++) {// 不处理第一列
if (w[i - 1] > j) {// 因为我们的程序是从1开始的,因此从w[i-1]开始
v[i][j] = v[i - 1][j];
} else {
if (v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
// 把当前的情况记录到path
path[i][j] = 1;
} else {
v[i][j] = v[i - 1][j];
}
}
}
}
for (int i = 0; i < v.length; i++) {
for (int j = 0; j < v[i].length; j++) {
System.out.print(v[i][j] + " ");
}
System.out.println();
}
// 输出最后我们是放入的哪些商品
int i = path.length - 1;// 行的最大下标
int j = path[0].length - 1;// 列的最大下标
while (i > 0 && j > 0) {// 从path的最后开始找
if (path[i][j] == 1) {
System.out.printf("第%d个商品放入到背包\n", i);
j -= w[i - 1];
}
i--;
}
}
}