01揹包問題

2021-08-21 20:28:29 字數 3255 閱讀 3299

動態規劃演算法一般用來求解最優化問題,當問題有很多可行解,而題目要求尋找這些解當中的「最大值」/「最小值」時,通常可以採用dp。

輸入

n=4(w,v)=

w=5----------

輸出7

遞迴函式搜尋

(1)有兩種可能:選或者不選;(2)使用遞迴,在遍歷完n個數的時候,判斷價值最大。

int rec(int i,int j)

else

if(j//無法挑選這個物品

res=rec(i+1,j);

}else

return res;

}

動態規劃

dp[i][j]為根據rec的定義,直接利用遞推式和二重迴圈計算出各項的值

for(int i=n-1;i>=0;i--)

}

關於狀態轉移方程的迴圈i方向問題,跟其遞推關係定義有關;如果是如下定義,則i的迴圈能正向進行。

dp[i+1][j]=dp[i][j];  (j

dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]); (其他)

個人理解總結:最重要就是動態轉移方程:

dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);

/*該問題可以描述為 「將前 i 件物品放入容量為 j 的揹包中」;

問題可以轉換為「只考慮第 i 件物品的策略(放或不放)」,

如果不放第 i 件物品,那麼問題就轉化為 「前 i-1 件物品放入容量為 j 的揹包中」;

如果放第 i 件物品,那麼問題就轉化為「前 i − 1 件物品放入剩下的容量為 v − w[i] 的揹包中」;此時獲得的最大價值就是 dp[i-1][j-w[i]]+v[i]

*/

具體實現:

//time: o(nw) memory: o(nw)

public

static

void

main(string args)

int w = in.nextint();

int dp = new

int[n+1][w+1];

for (int i = 1; i <= n; i++)

}system.out.println(dp[n][w]);

}

優化空間複雜度:如果只用乙個陣列 dp[w] ,能不能保證第 i

次迴圈結束後 dp[w] 中表示的就是我們定義的狀態 dp[i,w] 呢? dp[i,w] 是由 dp[i-1 ,w] 和

dp[i − 1,w-w[i] ] 兩個子問題遞推而來,能否保證在推 dp[i,w] 時(也即在第 i 次主迴圈中

推 dp[w] 時)能夠取用 dp[i − 1,w] 和 dp[i − 1,w− w[i] ] 的值呢?

事實上,這要求在每次主迴圈中我們以 重量 w 遞減順序計算 dp[w] ,這樣才

能保證計算 dp[w] 時 dp[w− w[i] ] 儲存的是狀態 dp[i − 1, w − w[i]] 的值。

//time: o(nw) memory: o(w)

public

static

void

main(string args)

int dp = new

int[w+1];

for (int i = 1; i <= n; i++)

}system.out.println(dp[w]);

}

初始化細節:我們看到的求最優解的揹包問題題目中,事實上有兩種不太相同的問法。有的題目

要求「恰好裝滿揹包」時的最優解,有的題目則並沒有要求必須把揹包裝滿。一種區別

這兩種問法的實現方法是在初始化的時候有所不同。

如果是第一種問法,要求恰好裝滿揹包,那麼在初始化時除了 f[0] 為 0 ,其它

f[1..v ] 均設為 −∞ ,這樣就可以保證最終得到的 f[v ] 是一種恰好裝滿揹包的最優解。

如果並沒有要求必須把揹包裝滿,而是只希望**盡量大,初始化時應該將 f[0..v ]

全部設為 0 。

題目:給定兩個字串s1s2…sn和t1t2…tn;求出這兩個字串的最長公共子串行的長度。

輸入

n=4m=4

s="abcd"

t="becd"

----------

輸出3("bcd")

定義dp[i][j]為s1s2…sn和t1t2…tn的公共子串行的長度,再結合圖和**就很容易理解。

/*

問題可以轉換為 「s中的前i個字元與t中的前j個字元的公共子串行長度dp[i][j]」;

如果當前s[i]==t[j],那麼問題就轉變為 「s中的前i-1個字元與t中的前j-1個字元的公共子串行長度 dp[i-1][j-1]+1 」;

如果不相等,那麼問題的轉變就有兩種可能性;

(1)s中的前i個字元與t中的前j-1個字元的公共子串行長度dp[i][j-1];

(2)s中的前i-1個字元與t中的前j個字元的公共子串行長度dp[i-1][j];

最大公共子串長度問題就是:

求兩個串的所有子串中能夠匹配上的最大長度是多少。

比如:"abcdkkk" 和 "baabcdadabc",

可以找到的最長的公共子串是"abcd",所以最大公共子串長度為4。

//動態規劃

public

class main}}

return max;

}public

static

void

main(string args)

}

揹包問題 01揹包問題

n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...

揹包問題 01揹包

有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...

揹包問題(01揹包)

1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...