DP(動態規劃)學習筆記

2021-10-10 07:46:25 字數 3695 閱讀 9182

揹包問題

01揹包每件物品最多使用一次

完全揹包每件物品有無限個

多重揹包每種物品最多有si個 (存在樸素版和優化版)

分組揹包沒組最多只能選 1 個

dp優化:對dp方程進行等價變形

dp最重要的就是公式推導(對於當前狀態的計算)

要滿足兩個條件:①不重 ②不漏

最簡單的01揹包

d p[

i][j

]=ma

x(dp

[i−1

][j]

,dp[

i−1]

[j−v

[i]]

+w[i

])

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

dp[i][

j]=m

ax(d

p[i−

1][j

],dp

[i−1

][j−

v[i]

]+w[

i]);

當前的值等於加入第i個物品和不加入第i個數(保證體積總值小於v)的最大的值。

1.樸素版:

#include using namespace std;

const int maxn=1e3+5;

int v[maxn],w[maxn];

int dp[maxn][maxn];

int main()

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

} cout<2.空間(和時間)優化版

可以使用滾動陣列來優化(節約空間)

同時在第二遍迴圈的時候節約了時間

因為f(i)這層只用到了f(i-1)這一層。

#include using namespace std;

const int maxn = 1e3+5;

int v[maxn],w[maxn];

int dp[maxn];

int main()

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

} cout《每件物品可以放入無限次,求最大價值。

1.樸素版

狀態轉移公式

d p[

i][j

]=ma

x(dp

[i−1

][j]

,dp[

i−1]

[j−k

∗v[i

]]+k

∗w[i

])

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

dp[i][

j]=m

ax(d

p[i−

1][j

],dp

[i−1

][j−

k∗v[

i]]+

k∗w[

i]);

相當於不選和選k個進行比較,找到最大的價值

#include using namespace std;

const int maxn = 1e3+5;

int v[maxn],w[maxn];

int dp[maxn][maxn];

int main()

} }cout<2.優化版

f [i

,j]=

f[i−

1,j−

v[i]

∗k]+

w[i]

∗k

f[i,j]=f[i-1,j-v[i]*k]+w[i]*k

f[i,j]

=f[i

−1,j

−v[i

]∗k]

+w[i

]∗kf [ i , j ] = max ( f [ i - 1 , j ] , f [ i - 1 , j - v ] + w , f [ i - 2 , j - 2 * v ] + 2 * w… )

f [ i , j - v ] = max ( f [ i -1 , j - v ] , f [ i - 2 , j - v * 2] + w … )

f [ i , j ] = max( f [ i - 1 , j ] , f [ i , j - v ] + w ) //表示當滿足可以放第i個物品的時候判斷是否價值會更大。

//普通優化

#include using namespace std;

const int n = 1e3+4;

int v[n],w[n];

int dp[n][n];

int main()

} coutconst int n = 1e3+4;

int v[n],w[n];

int dp[n];

int main()

} cout《每件物品最多能放入si次,求最大價值。

1.樸素版

時間複雜度o(n v s)

#include using namespace std;

const int n = 1e3+4;

int v[n],w[n],s[n];

int dp[n][n];

int main()

} }cout<2.優化為01揹包版

二進位制優化方式

將si個物品打包好後簡化成01揹包問題。

例:1023

1 2 4 8 ,,,512 進行01揹包可以湊出1-1023中任意的數。

1 ->0 1

1 2 -> 0 1 2 3

1 2 3 -> 0 1 2 3 4 5 6

1…512 -> 0-1023

這樣就把應該列舉的1024次簡化為了10次。

1 2 4 8 16 32 64 73(200-127)

8次可以簡化200次 lg 200

優化後的時間複雜度o(n v lg s)

#include using namespace std;

const int n = 250005,m=2010;

int v[n],w[n],dp[n],cnt;

int main()

if(s>0)

} n=cnt;

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

} cout<4.分組揹包

​ 如果是從當前這層數組更新,那麼從前往後遍歷。

每組要一種,求最大價值

直接上滾動陣列版

#include #include using namespace std;

const int n = 110;

int n,m;

int v[n][n],w[n][n],s[n];

int f[n];

int main()

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

}} }

cout

}

學習筆記 動態規劃 I 初識DP

更新日期 2018 3 16,2018 12 03 動態規劃,簡稱dp dynamic programming 簡介1簡介2 動態規劃十分奇妙,它可以變身為記憶化搜尋,變身為遞推,甚至有時可以簡化成乙個小小的算式。動態規劃十分靈活,例如 noip2018 pj t3 擺渡車 寫法有很多很多,但時間 ...

動態規劃 dp

威威貓系列故事 打地鼠 威威貓最近不務正業,每天沉迷於遊戲 打地鼠 每當朋友們勸他別太著迷遊戲,應該好好工作的時候,他總是說,我是威威貓,貓打老鼠就是我的工作!無話可說.我們知道,打地鼠是一款經典小遊戲,規則很簡單 每隔乙個時間段就會從地下冒出乙隻或多隻地鼠,玩遊戲的人要做的就是打地鼠。假設 1 每...

動態規劃,dp

線性動規區間動規樹形動規 區間動規 根據題目要求,全域性最優滿足區域性最優 典型題例 加分二叉樹 洛谷1040 題目介紹 題目描述 設乙個n 個節點的二叉樹t 的中序遍歷為 1,2,3,n 其中數字 1,2,3,n 為節點編號。每個節點都有乙個分數 均為正整數 記第j 個節點的分數為dj。二叉樹t ...