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