單調佇列優化多重揹包

2021-09-12 05:44:36 字數 2661 閱讀 3222

多重揹包:n個物品,揹包承重m,每個物品 重量:wi 價值vi 個數為ci

普通多重揹包複雜度:o(nmc)

**:

for

(int i=

1;i<=n;i++

)for

(int j=

1;j<=m;j++

)for

(int k=

1;k<=c[i]

&& k*w[i]

<=j;k++

) f[i]

[j]=

max(f[i]

[j],f[i-1]

[j-k*w[i]

]+k*v[i]

);

單調佇列優化的多重揹包複雜度:o(nm)

考慮把o(c )的轉移壓縮為o(1)

變形:a=j/w[i]

b=j%w[i]

j=b+aw[i]

思路:承重為j時,不考慮ci限制時最多選a個i號元素。假設a個中不選k個,即選a-k個。

轉移方程:

f[i]

[j]=

max(f[i]

[j],f[i-1]

[j-(a-k)

*w[i]]+

(a-k)

*v[i]);

等價於f[i]

[j]=

max(f[i]

[j],f[i-1]

[b+k*w[i]]+

(a-k)

*v[i]);

即是f[i]

[j]=

max(f[i]

[j],f[i-1]

[b+k*w[i]

]-k*v[i]

)+a*v[i]

;//(a-k<=c[i])

這樣max裡面就與j無關了,只與b和k有關。

那麼我們列舉b和k就行了。然後用單調佇列維護max。

b+a*w[i]即為j恰好可以表示1~m的所有數

求f[i][j]用到哪些狀態,我來列舉下就一目了然了

f[i]

[b+0

*w[i]]=

max(f[i-1]

[b+0

*w[i]]-

0*v[i])+

0*v[i]

;f[i]

[b+1

*w[i]]=

max(f[i-1]

[b+0

*w[i]]-

0*v[i]

,f[i-1]

[b+1

*[w[i]])

-1*v[i])+

1*v[i]

;f[i]

[b+2

*w[i]]=

max(f[i-1]

[b+0

*w[i]]-

0*v[i]

,f[i-1]

[b+1

*[w[i]])

-1*v[i]

,f[i-1]

[b+2

*w[i]]-

2*v[i]])

+2*v[i];.

...f[i]

[b+k*w[i]]=

max(f[i-1]

[b+0

*w[i]]-

0*v[i]

,f[i-1]

[b+1

*[w[i]])

-1*v[i]

,f[i-1]

[b+2

*w[i]]-

2*v[i]].

...f[i-1]

[b+a*w[i]

]-k*v[i]

)+k*v[i];.

...f[i]

[b+a*w[i]]=

max(f[i-1]

[b+0

*w[i]]-

0*v[i]

,f[i-1]

[b+1

*[w[i]])

-1*v[i]

,f[i-1]

[b+2

*w[i]]-

2*v[i]].

...f[i-1]

[b+a*w[i]

]-a*v[i]

)+a*v[i]

;

可以發現f[i][b+k*w[i]]的轉移規律,我們就拿單調佇列把max裡的東西存下來,這樣就不用每次列舉選多少個i號物品了

**片:

for

(int b=

0; b; b++

)}

例題:hdu2191

#include

using namespace std;

#define n 110

#define inf 999999999

int t,n,m,w[n]

,v[n]

,c[n]

,ans,he,ta;

int f[n]

[7005

],q[

7005

],num[

7005];

intmain()

}}printf

("%d\n"

,f[n]

[m]);}

return0;

}

多重揹包單調佇列優化思路 單調佇列優化多重揹包問題

6.多重揹包問題 iii acwing題庫 www.acwing.com 揹包九講bilibili www.bilibili.com 從公式中可以看出f j 和f j c 都是從s 1個數裡面取最大值,計算f j c 時只是將滑動視窗右移了一步,類似下圖的效果 只不過移動的時候,前面的s個元素都增加...

單調佇列優化多重揹包

多重揹包的最原始的狀態轉移方程 令 c i min num i j v i f i j max f i 1 j k v i k w i 1 k c i 這裡的 k 是指取第 i 種物品 k 件。如果令 a j v i b j v i 那麼 j a v i b.這裡用 k 表示的意義改變,k 表示取第...

單調佇列優化多重揹包

應該是個經典演算法,稍微記錄一下 用 w i 表示重量,v i 表示價值 那麼不難寫出轉移方程 f i j max f i 1 j k w i k v i 考慮用單調佇列優化。我們若要用單調佇列優化,那麼必須滿足轉移時所需要的狀態只與 k 有關 這裡要用到乙個神仙操作,對 j w i 分類 因為對於...