1. 程式人生 > >01揹包問題(Java實現)

01揹包問題(Java實現)

【問題描述】

         一個旅行者有一個最多能裝m公斤的揹包,現在有n中物品,每件的重量分別是W1、W2、……、Wn,每件物品的價值分別為C1、C2、……、Cn, 需要將物品放入揹包中,要怎麼樣放才能保證揹包中物品的總價值最大?

【思路】

       假設前n個物品,總承重為j,物品的重量為w,其最大價值為v[n,j]。   在揹包的總承重不變的前提下,一個物品是否放入揹包中直接影響到後面的物品是否能放入到揹包中,即一個物品很重同事物品價值又很低時,若裝入揹包中直接導致其他更多的物品無法放入揹包中,從而使得揹包中的最大總價值變低。   當揹包的承重為0,或者不將物品放入揹包時,揹包中的最大總價值均為0,即v[n,0]=v[0,n]=0。   放入當前物品n超過揹包的最大承重時,則無法將該物品放入揹包中,即v[n,j]=v[n-1,j]。    放入當前物品n不超過揹包的最大承重時,則當前物品放入揹包時的最大價值為vn+v[n-1,j-wn],不放入揹包時的最大價值為v[n-1,j],因此對於當前物品是否放入揹包中所能獲得的最大價值

v[n,j]=max{ v[n-1,j],vn+v[n-1,j-wn] }

狀態轉化方程為:

【程式碼實現】

      /**
	 * @param m : 表示揹包的最大容量
	 * @param n : 表示商品的個數
	 * @param w : 表示商品重量陣列
	 * @param p : 表示商品價值陣列
	 * 
	 */
	public static int[][] DP_01bag(int m,int n,int w[],int p[]){
		//c[i][m] 表示前i件物品恰好放入重量為m的揹包時的最大價值
		int c[][] = new int[n+1][m+1];
		
		for(int i=0;i<n+1;i++){
			c[i][0] = 0;
		}
		for(int j=0;j<m+1;j++){
			c[0][j] = 0;
		}
		for(int i=1;i<n+1;i++){
			for(int j=1;j<m+1;j++){
     //當物品為i件重量為j時,如果第i件的重量(w[i-1])小於重量j時,c[i][j]為下列兩種情況之一:
     //(1)物品i不放入揹包中,所以c[i][j]為c[i-1][j]的值
     //(2)物品i放入揹包中,則揹包剩餘重量為j-w[i-1],所以c[i][j]為c[i-1][j-w[i-1]]的值加上當前物品i的價值	
				if(w[i-1] <= j){
					if(c[i-1][j] <c[i-1][j-w[i-1]]+p[i-1]){
						c[i][j] = c[i-1][j-w[i-1]]+p[i-1];
					}else{
						c[i][j] = c[i-1][j];
					}
					
				}else{
					c[i][j] = c[i-1][j];
				}
			}
		}
		return c;
		
	}