揹包問題模板

2021-10-08 22:26:34 字數 3635 閱讀 6076

#

include

#include

using

namespace std;

const

int n =

10010

;int f[n]

, v[n]

, w[n]

;// f[i][j]: 前i種物品中,空間為j時的最大價值。

intmain()

#

include

#include

using

namespace std;

const

int n =

10010

;int f[n]

, v[n]

, w[n]

;// f[i][j]: 前i種物品中,空間為j時的最大價值。

intmain()

注意: 01揹包與完全揹包的**僅在第二維的遍歷順序有差異,這是因為兩者狀態轉移方程的不同:

01揹包:f[i]

[j]= max(f[i-1]

[j], f[i-1]

[j-v[i]

] + w[i]);

完全揹包:f[i]

[j]= max(f[i-1]

[j], f[i]

[j-v[i]

]] + w[i]

);

可以發現01揹包由第i-1行轉移而來,完全揹包由第i行轉移而來。

二進位制優化:對於可選n次的揹包,可將其合併成若干個揹包(合併得到揹包的組合必須能夠表示1-n中的任意乙個數), 這樣可用01揹包求解。

#

include

#include

using

namespace std;

const

int n =

23000

;int f[n]

, v[n]

, w[n]

;int

main()

if(s) v[cnt]

= s*x, w[cnt++

]= s*y;

}for

(int i =

1; i < cnt; i++

)for

(int j = m; j >= v[i]

; j--

) f[j]

=max

(f[j]

, f[j-v[i]

]+ w[i]);

cout << f[m]

;return0;

}

滑動視窗優化:通過滑動視窗求最大值,時間複雜度o(n*v), 其中n為物品數,v為給定的空間。

f(i,j)=max(f(i−1,j),f(i−1,j−v)+w,⋯,f(i−1,j−sv)+sw)

f(i,j−v)=max(f(i−1,j−v),f(i−1,j−2v)+w,⋯,f(i−1,j−(s+1)v)+sw)

#

include

#include

#include

using

namespace std;

const

int n =

1010

, m =

20010

;int v[n]

, w[n]

, s[n]

;int dp[m]

, g[m]

, qq[m]

;int

main()

for(

int i =

1; i <= n; i++

)while

(hh <= tt && g[qq[tt]]+

(k - qq[tt]

)/ v[i]

* w[i]

<= g[k]

) qq[

++tt]

= k;

if(hh <= tt) dp[k]

= g[qq[hh]]+

(k - qq[hh]

)/ v[i]

* w[i];}

}}cout << dp[m]

<< endl;

return0;

}

#

include

using

namespace std;

const

int n =

110;

int f[n]

, v[n]

[n], w[n]

[n], cnt[n]

;// f[i][j]: 前i組物品中,空間為j時的最大價值。

// v[i][j]: 第i組物品的第j個; cnt[i]: 第i組的物品個數。

intmain()

for(

int i =

1; i <= n; i++

)

cout << f[m]

;return0;

}

#

include

using

namespace std;

const

int n =

1010

;int dp[n]

;// dp[i][j]: 前i類物品體積為j的最大價值

intmain()

else

for(

int k =

1; k <= s; k *=2)

s -= k;}if

(s)}

} cout << dp[m]

<< endl;

return0;

}

#

include

#include

#include

using

namespace std;

const

int n =

110;

int n, m;

int v[n]

, w[n]

;int h[n]

, e[n]

, ne[n]

, idx;

int dp[n]

[n];

// dp[i][j]: 對於i為根節點的子樹,體積為j時的最大價值

void

add(

int a,

int b)

void

dfs(

int u)}}

// 加上根節點的值

for(

int j = v[u]

; j <= m; j++

) dp[u]

[j]+= w[u];}

intmain()

else

}dfs

(root)

; cout << dp[root]

[m]<< endl;

return0;

}

揹包問題模板

特點 每種物品只有一件 子問題定義狀態 bag i v 前i件物品放到乙個容量為v的揹包中可以獲得最大價值 轉移狀態方程 bag i v max bag i 1 v bag i 1 v weight i value i 模板 include include using namespace std i...

揹包問題模板

01揹包在時間複雜度上都是n n v 在這個基礎之上已經不能再進行優化了,在空間複雜度上,我們首先看一下複雜度為o n v 的程式 for int i 1 i n i for int j 0 j w j 但是我們還可以將空間複雜度壓縮為o v 我們會發現這裡每次更新第i層都只是看第i 1層,其他層的...

模板 揹包問題

include include define max a,b a b a b using namespace std const int n 1005 int n,v,v n w n int dp n voidf intmain f printf d n dp v return0 include i...