單調佇列優化多重揹包

2021-07-23 19:58:01 字數 1451 閱讀 3254

多重揹包的最原始的狀態轉移方程:

令 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 表示取第 i 種物品的件數比 a 少幾件。

那麼 f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)

可以發現,f[i-1][b+k*v[i]] - k*w[i] 只與 k 有關,而這個 k 是一段連續的。我們要做的就是求出 f[i-1][b+k*v[i]] - k*w[i] 在 k 取可行區間內時的最大值。

k 取可行區間內時的最大值。k 取可行區間內時的最大值。k 取可行區間內時的最大值。

這句話特別重要,兩個晚上理解了這句話。

m[i] = min(n[i], j / v[i])。

f[i][j]就是求這個佇列最大長度為m[i] + 1時,佇列中元素的最大值,加上a * w[i]。

這就可以使用單調佇列優化。

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

t = f[k] - cnt * wi;

q1[++tail1] = t;

while (head2 < tail2 && q2[tail2] < t)

--tail2;

q2[++tail2] = t;

f[k] = q2[head2 + 1] + cnt * wi;//可行性區間為cnt

++cnt;}}

}

f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)

例題 codevs

5429

#include

using

namespace

std;

int f[10000],num[10000],v[10000],w[10000];int ps,qs,pe,qe;

int q1[10000],q2[10000];

int main()

int ans=0;

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

int t=f[k]-cnt*v[i];

q1[++pe]=t;

while (qs<=qe&&t>q2[qs])

--qe;

q2[++qe]=t;

f[k]=q2[qs]+cnt*v[i];}}

ans=max(ans,f[m]);

}cout

<}

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

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

單調佇列優化多重揹包

多重揹包 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 ...

單調佇列優化多重揹包

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