混合背包(单调队列优化多重背包)(模板)

简述

如标题所述,放一下混合背包最优时间的模板

 代码区

#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];
            }
        }
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/winter-bamboo/p/11545483.html