动态规划 01背包

此文章系读【大熊先生】的这篇【基础算法系列总结:动态规划(解公司外包成本问题)】 读后感。

 

接受了大神的洗礼之后,其实还是有一些地方不太明白,同样是动态规划,怎么例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 + "\t");
36         }
37         System.out.println();
38         for(int i = 0; i <= limit; i++){
39             System.out.print(a[i] + "\t");
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 }
01背包

我感觉看起来更简洁明了点~

感谢【大熊先生

 

至此

posted @ 2015-08-27 16:23  之奇一昂  阅读(185)  评论(0编辑  收藏  举报