混合背包(单调队列优化多重背包)(模板)
简述
如标题所述,放一下混合背包最优时间的模板
代码区
#include<bits/stdc++.h> using namespace std; const int Max = 1e5+10; int n, v; int val[Max], vol[Max], num[Max]; int que[Max]; int dp[Max]; void work() { memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; i++) { if (num[i] == 1) //01背包 { for (int j = v; j >= vol[i]; j--) dp[j] = max(dp[j], dp[j - vol[i]] + val[i]); continue; } if (vol[i] * num[i] >= v) //完全背包,这个比较关键,因为用单调队列处理非常耗时 { for (int j = vol[i]; j <= v; j++) dp[j] = max(dp[j], dp[j - vol[i]] + val[i]); continue; } for (int res = 0; res < vol[i]; res++) //枚举余数 { int head = 0, tail = -1; for (int k = 0; k <= (v - res) / vol[i]; k++) //枚举k',即等差数列的项数,每次更新同余数的数 //因为只有余数相同的数才会互相影响 { int value = dp[k * vol[i] + res] - k * val[i]; //当前的价值 if (tail - head == k) //就算用尽所有材料也无法从que[head]转移 head++; while (head <= tail && que[tail] <= value) //取最大值 tail--; tail++; que[tail] = value; dp[k * vol[i] + res] = que[head] + k * val[i]; } } } }