//j-kv 是%v余数相同的点 //设余数是r #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 20010; int n, m; int f[N], g[N], q[N]; int main() { cin >> n >> m; for (int i = 0; i < n; i ++ ) { int v, w, s; cin >> v >> w >> s; memcpy(g, f, sizeof f);//存储上一层,因为会用到上一层的数数据 for (int j = 0; j < v; j ++ ) {//余数 int hh = 0, tt = -1;//滑动窗口,队列 for (int k = j; k <= m; k += v) { //表示每一个体积 if (hh <= tt && q[hh] < k - s * v)//当队列不空,而且已经滑出窗口 hh ++ ; if (hh <= tt)//如果队列不空,更新当且最大值 //最大值位队头元素 //q[hh]对应最大值对应下标,基础值再加上收益 //收益是指里面装了多少个第i个物品,多少个:k-q[hh]/v个,再乘价值 //中间空余了多少个第i个物品的体积 空余一个,就可以多放一个物品进来 f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w); //弹出没有用的元素 下标减去初始余数 //当队列不空,而且队尾价值小于当前价值,队尾就没有意义,弹出 while (hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w) tt -- ; q[ ++ tt] = k;//存每个体积 } } } cout << f[m] << endl; return 0; }
AcWing 6. 多重背包问题 III
猜你喜欢
转载自www.cnblogs.com/QingyuYYYYY/p/11979220.html
今日推荐
周排行