多重揹包的最原始的狀態轉移方程:
令 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 分類 因為對於...