动态规划(java)

问题一:最大子组和问题
子组中的元素可能是正负或0,思路:
最大子组和就是所有可能的子组和中最大的,那么可能比较大的首先有一个初始值(0),然后如果有比初始值大的子组和,就用来替代当前的最大子组和,直到遍历结束再也没有比当前子组和更大的。
当子组和为负的时候,肯定不是我们期望的最大子组和的一部分,因为负的累积值和后续的子组元素的和,肯定小于后续子组元素的和。这时可以排除该子组和的元素,从使累计子组和为正的开始重新统计。
当遍历结束最大子组和等于初始值0时,说明数组元素都是非正的,那么遍历找出最大的负数。

/** * @author Flying *题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 *求所有子数组的和的最大值。要求时间复杂度为O(n)。 浙大数据结构课本上有 思路: *求连续数字之和,当和为负值,抛弃.当和为正值,比较其与最大值,如大于,则替换之 *http://zhedahht.blog.163.com/blog/static/254111742007219147591/ *http://blog.csdn.net/v_JULY_v/article/details/6444021 */ public class FindMaxSumOfSubArray {/** * @param args */ public static void main(String[] args) { FindMaxSumOfSubArray f = new FindMaxSumOfSubArray(); int[] arr = { 1, -2, 3, 10, -4, 7, 2, -5 }; System.out.println("MaxSum:" + f.findMaxSum(arr)); }public Integer findMaxSum(int[] arr) { int curSum = 0; int maxSum = 0; int len = arr.length; if (arr == null || len == 0) { return null; }for (int i = 0; i < len; i++) { curSum += arr[i]; if (curSum < 0) { curSum = 0; } if (curSum > maxSum) { maxSum = curSum; } }// all data are negative if (maxSum == 0) { for (int i = 0; i < len; i++) { if (i == 0) { maxSum = arr[i]; } if (arr[i] > maxSum) { maxSum = arr[i]; } } } return maxSum; } }

问题二:背包问题
这是我看过讲背包问题,最容易理解的帖子
http://m.blog.csdn.net/article/details?id=7722810
01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }
f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值。
Pi表示第i件物品的价值。
决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中吗 ?
题目描述:
有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
动态规划(java)
文章图片

只要你能通过找规律手工填写出上面这张表就算理解了01背包的动态规划算法。
首先要明确这张表是至底向上,从左到右生成的。
为了叙述方便,用e2单元格表示e行2列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为2的背包,那么这个背包的最大价值是0,因为e物品的重量是4,背包装不了。
对于d2单元格,表示只有物品e,d时,承重为2的背包,所能装入的最大价值,仍然是0,因为物品e,d都不是这个背包能装的。
同理,c2=0,b2=3,a2=6。
对于承重为8的背包,a8=15,是怎么得出的呢?
根据01背包的状态转换方程,需要考察两个值,
一个是f[i-1,j],对于这个例子来说就是b8的值9,另一个是f[i-1,j-Wi]+Pi;
在这里,
f[i-1,j]表示我有一个承重为8的背包,当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值
f[i-1,j-Wi]表示我有一个承重为6的背包(等于当前背包承重减去物品a的重量),当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值
f[i-1,j-Wi]就是指单元格b6,值为9,Pi指的是a物品的价值,即6
由于f[i-1,j-Wi]+Pi = 9 + 6 = 15 大于f[i-1,j] = 9,所以物品a应该放入承重为8的背包
下面是java实现:
http://blog.csdn.net/lovesqcc/article/details/5859223
public class KnapsackProblem { /** 指定背包 */ private Knapsack[] bags; /** 总承重*/ private int totalWeight; /** 给定背包数量*/ private int n; /** 前 n 个背包,总承重为 totalWeight 的最优值矩阵*/ private int[][] bestValues; /** 前 n 个背包,总承重为 totalWeight 的最优值 */ private int bestValue; /** 前 n 个背包,总承重为 totalWeight 的最优解的物品组成 */ private ArrayList bestSolution; public KnapsackProblem(Knapsack[] bags, int totalWeight) { this.bags = bags; this.totalWeight = totalWeight; this.n = bags.length; if (bestValues == null) { bestValues = new int[n+1][totalWeight+1]; } } /** * 求解前 n 个背包、给定总承重为 totalWeight 下的背包问题 * */ public void solve() { System.out.println("给定背包:"); for(Knapsack b: bags) { System.out.println(b); } System.out.println("给定总承重: " + totalWeight); // 求解最优值 for (int j = 0; j <= totalWeight; j++) { for (int i = 0; i <= n; i++) { if (i == 0 || j == 0) { bestValues[i][j] = 0; } else { // 如果第 i 个背包重量大于总承重,则最优解存在于前 i-1 个背包中, // 注意:第 i 个背包是 bags[i-1] if (j < bags[i-1].getWeight()) { bestValues[i][j] = bestValues[i-1][j]; } else { // 如果第 i 个背包不大于总承重,则最优解要么是包含第 i 个背包的最优解, // 要么是不包含第 i 个背包的最优解, 取两者最大值,这里采用了分类讨论法 // 第 i 个背包的重量 iweight 和价值 ivalue int iweight = bags[i-1].getWeight(); int ivalue = https://www.it610.com/article/bags[i-1].getValue(); bestValues[i][j] = Math.max(bestValues[i-1][j], ivalue + bestValues[i-1][j-iweight]); } // else } //else } //for } //for // 求解背包组成 if (bestSolution == null) { bestSolution = new ArrayList(); } int tempWeight = totalWeight; for (int i=n; i >= 1; i--) { if (bestValues[i][tempWeight] > bestValues[i-1][tempWeight]) { bestSolution.add(bags[i-1]); // bags[i-1] 表示第 i 个背包 tempWeight -= bags[i-1].getWeight(); } if (tempWeight == 0) { break; } } bestValue = https://www.it610.com/article/bestValues[n][totalWeight]; } /** * 获得前n 个背包, 总承重为 totalWeight 的背包问题的最优解值 * 调用条件: 必须先调用 solve 方法 * */ public int getBestValue() { return bestValue; } /** * 获得前n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵 * 调用条件: 必须先调用 solve 方法 * */ public int[][] getBestValues() { return bestValues; } /** * 获得前n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵 * 调用条件: 必须先调用 solve 方法 * */ public ArrayList getBestSolution() { return bestSolution; } public static void main(String[] args) { Knapsack[] bags = new Knapsack[] { new Knapsack(2,13), new Knapsack(1,10), new Knapsack(3,24), new Knapsack(2,15), new Knapsack(4,28), new Knapsack(5,33), new Knapsack(3,20), new Knapsack(1, 8) }; int totalWeight = 12; KnapsackProblem kp = new KnapsackProblem(bags, totalWeight); kp.solve(); System.out.println(" -------- 该背包问题实例的解: --------- "); System.out.println("最优值:" + kp.getBestValue()); System.out.println("最优解【选取的背包】: "); System.out.println(kp.getBestSolution()); System.out.println("最优值矩阵:"); int[][] bestValues = kp.getBestValues(); for (int i=0; i < bestValues.length; i++) { for (int j=0; j < bestValues[i].length; j++) { System.out.printf("%-5d", bestValues[i][j]); } System.out.println(); } } }

public class Knapsack { /** 背包重量*/ private int weight; /** 背包物品价值*/ private int value; /*** * 构造器 */ public Knapsack(int weight, int value) { this.value = https://www.it610.com/article/value; this.weight = weight; } public int getWeight() { return weight; } public int getValue() { return value; } public String toString() { return"[weight: " + weight + " " + "value: " + value + "]"; } }

【动态规划(java)】最长公共子串
http://blog.csdn.net/biangren/article/details/8038605

    推荐阅读