演算法基礎-動態規劃 (1) 01揹包問題
阿新 • • 發佈:2019-02-03
最近閒的無聊,演算法一直是弱項,正好hihocoder上面開始了每週的比賽,
這周的題目是01揹包問題。正好歸納和總結一下。
所有的動態規劃問題都兩個特點:
1、重複子問題:一個問題可以轉化成幾個同類型的子問題。
2、後無關性:前一個問題產生的決策和結果,對下一個問題沒有影響。
說白了,就是你能吧問題寫成簡單的數學遞迴表示式:
對於01揹包問題,建模很關鍵,
這裡面有幾個關鍵量
物品個數N
能容納的重量M
每個物品的價值V(i)
每個物品的重量w(i)
我們要想好這個數學表示式
對於每個物品而言,有兩種狀態,被選上和不被選上, 即0和1狀態。而對整個揹包而言 能夠承受的重量就是裡面物品的加和,同樣價值一樣也是加和。
我們希望揹包儘可能裝得多,而且產生的價值最大,(最重要的的是總價值最高)
所以整個表示式應該以價值作為衡量因素。
下面是表示式:
N個物品,揹包有M重量空餘,等於在前N-1選擇最大的,一種是不選擇第N-1個物品,另一種是選擇第N-1個物品,並佔據了揹包Wn的重量,但提供了Vn的價值。
下面是三種程式碼形式,孰優孰劣,大家一眼就能開出來。
public int getcurrentVlue(int i,int j){ if(i==0){ if(j>=0) return 0; } if(j<0) return Integer.MIN_VALUE; return max (getcurrentVlue(i-1, j),getcurrentVlue(i-1, j-w[i-1])+v[i-1]); }
public int getvalue(int sum,int wei){
int[] [] value =new int [sum][wei];
for(int i=1;i<sum;i++){
for(int j=0;j<wei;j++){
if(j<w[i-1]) value[i][j] = value[i-1][j];
else{
value[i][j] = max (value[i-1][j],value[i-1][j-w[i-1]]+v[i-1]);
}
}
}
return wei;
}
public int getvalues(int sum, int wei) { int[] value = new int[wei + 1]; for (int i = 1; i < sum + 1; i++) { for (int j = wei; j > w[i - 1] - 1; j--) { value[j] = value[j] > value[j - w[i - 1]] + v[i - 1] ? value[j] : value[j - w[i - 1]] + v[i - 1]; } } return value[wei]; }
顯然第三種效果最好。