1. 程式人生 > >0-1揹包問題遞迴與非遞迴實現

0-1揹包問題遞迴與非遞迴實現

0-1揹包問題有很多介紹,現在先不做說明,有時間補上。以下是遞迴的實現

package test;

public class Package01 {
	
	public int f(int n, int V,int[] w,int[] v)
	{
	  if (n==0 || V==0)//當物品數量為0,或者揹包容量為0時,最優解為0
	  {
	     return 0;
	  }
	  else
	  {
	      //如果當前要判斷的物品重量大於揹包當前所剩的容量,那麼就不選擇這個物品
	      //在這種情況的最優解為f(n-1,C)
	      if (w[n-1]>V) return f(n-1,V,w,v);
	      else
	      {
	    	   //如果當前待判斷的物品重量wi
	    	   int tmp1 = f(n-1,V,w,v);//不選擇物品i的情況下的最優解
	    	   int tmp2 = v[n-1] + f(n-1,V-w[n-1],w,v);//選擇物品i的情況下的最優解
	    	   //返回選擇物品i和不選擇物品i中最優解大的一個
	    	   return tmp1 > tmp2?tmp1:tmp2;
	       }     
	   }
	}
	public static void  main(String args[])
	{
		int w[]={1,3,4,5};//物品重量陣列
		int v[]={2,30,44,20};//物品價值陣列
		Package01 pa=new Package01();
		int maxvalue = pa.f(4,4,w,v);
		System.out.println("Maximum Value is: "+maxvalue);
	}
}


非遞迴的實現如下:

    public static int package(int n,int V,int [] w,int [] v){
        int [] f=new int[V+1];
        for (int i=1;i<=n;i++){
            for (int j=V;j>=w[i];j--){
                f[j]=Math.max(f[j],f[j-w[i]]+v[i]);
            }
        }
        return f[V];
    }

非遞迴的過程如下:

測試資料:


10,3
3,4
4,5
5,6

先將f[] 全部初始化為0,其實也代表這個揹包陣列適應物品為空的時候所能容納的最大物品價值。

下圖中,黃色為當前正在操作的時候,黃色以上為上一次的陣列狀態,黃色以下可以不用看,那是以後的狀態。


之後的思想是將物品不斷新增進物品陣列中,然後更新揹包陣列的所能容納的最大物品價值。

新增第一個物品後:


新增完畢時是最後一行。

需要注意的是在更新揹包所能容納的最大物品價值時需要從後往前去更新,也就是下圖的過程需要從W~w


因為按照揹包問題的求解策略,大的揹包容量所能容納的最大物品價值是根據小 的揹包容量所能容納的最大物品價值計算出的,先更新大的揹包容量的值不會影響之前的小的揹包容量。

完全揹包和0-1在非遞迴實現上相似,只是完全揹包是使用正序的去更新陣列,而0-1揹包是逆序的去更新。

完全揹包可以參考我的另一篇文章(自己的部落格網站):http://amazingwu.xyz/2017/05/22/%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85/

最後本文參考了:http://blog.csdn.net/luojinping/article/details/6900788