此文章系读【大熊先生】的这篇【基础算法系列总结:动态规划(解公司外包成本问题)】 读后感。
接受了大神的洗礼之后,其实还是有一些地方不太明白,同样是动态规划,怎么例1是一个二维数组,到了例二就可以用一维数组了呢?
这让我回家想了一晚上……(原谅我菜),才想明白了些。
例1要求是同一物品不能重复使用,而我们例2写的循环是从左至右,如果采用一维数组的话,很可能当J循环到中后部分,a[j]与a[j - w[i]]比较时,a[j -w[i]]的值已经包含了p[i],也就是说此处导致w[i]物品被使用多次。
而例2并没有限制重复使用的次数,所以从左至右的循环解决例2问题时恰到好处~反而,当从右至左循环时,该算法对于例2就是一个错误答案了。
但是!这个思路竟然变成了例1的答案了……
原因如下:当循环从右至左时,能够保证j左边的数值是上一次循环修改过的,而本次循环肯定没有动过,所以保证了物品的使用次数(1或0次)不是多次。
因此,我们可以这样写代码来解例1:

1 package suanfa; 2 3 /** 4 * 5 * 6 * @author kischn@163.com 7 * @version 1.0 8 */ 9 public class MyDongGui2 { 10 11 int[] a = new int[100];//java数组不需要初始化,默认全是0 12 13 int limit = 4;//不得超过的容量 14 15 int w[] = {1,1,3,2}; 16 int p[] = {12,10,20,15}; 17 18 public int max(int a, int b){ 19 return a > b ? a : b; 20 } 21 22 public void doCalc(){ 23 int n = w.length; 24 for(int i = 0; i < n; i++){ 25 for(int j = limit; j > 0; j--){//倒序保证j左边的是上一次循环的数据 26 if(w[i] <= j){ 27 a[j] = max(a[j], a[j-w[i]] + p[i]); 28 } 29 } 30 } 31 } 32 33 public void print(){ 34 for(int i = 0; i <= limit; i++){ 35 System.out.print(i + " "); 36 } 37 System.out.println(); 38 for(int i = 0; i <= limit; i++){ 39 System.out.print(a[i] + " "); 40 } 41 } 42 43 44 public static void main(String[] args) { 45 MyDongGui2 mg2 = new MyDongGui2(); 46 mg2.doCalc(); 47 mg2.print(); 48 } 49 50 }
我感觉看起来更简洁明了点~
感谢【大熊先生】
至此