AcWing算法提高课 多重背包问题的单调队列优化

多重背包问题可以用单调队列进行优化

原理见:提高课1.3.1 背包模型(一)

离题:6. 多重背包问题 III

单调队列的deque实现如下:

复制代码
#include<bits/stdc++.h>
using namespace std;

int v[1010];
int w[1010];
int s[1010];
int dp[1010][20010];
int main()
{
    int N,V;
    cin>>N>>V;
    for(int i=1;i<=N;i++)
    {
        cin>>v[i]>>w[i]>>s[i];
    }
    
    for(int i=1;i<=N;i++)
    {
        for(int j=0;j<v[i];j++)
        {
            deque<int> que;
            for(int k=j;k<=V;k+=v[i])
            {
                while(que.size())
                {
                    if(dp[i-1][k]>=dp[i-1][que.back()]+(k-que.back())/v[i]*w[i])
                        que.pop_back();
                    else 
                        break;
                }
                que.push_back(k);
                if(k-que.front()>s[i]*v[i])
                    que.pop_front();
                
                if(que.size()!=0)
                    dp[i][k]=dp[i-1][que.front()]+(k-que.front())/v[i]*w[i];
                else
                    dp[i][k]=dp[i-1][k];

            }

        }
    }
    int res=0;
    for(int i=0;i<=V;i++) res=max(res,dp[N][i]);
    cout<<dp[N][V]<<endl;
    
    
}
View Code
复制代码

注意,由于deque速度比较慢,在数据量较大的情况下,可能会超时。

故单调队列推荐使用数组进行模拟。

数组模拟就是使用hh和tt记录队列的头部和队列的尾部的下一个位置,非常直观。

推荐写完deque的解法后,在直接修改即可。

复制代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

int v[1010];
int w[1010];
int s[1010];
int dp[1010][20010];
int que[20010];
int main()
{
    int N,V;
    cin>>N>>V;
    for(int i=1;i<=N;i++)
    {
        cin>>v[i]>>w[i]>>s[i];
    }
    
    for(int i=1;i<=N;i++)
    {
        for(int j=0;j<v[i];j++)
        {
            int hh=0,tt=0;
            for(int k=j;k<=V;k+=v[i])
            {
                while(hh<tt)
                {
                    if(dp[i-1][k]>=dp[i-1][que[tt-1]]+(k-que[tt-1])/v[i]*w[i])
                        tt--;
                    else 
                        break;
                }
                que[tt]=k;
                tt++;
                if(k-que[hh]>s[i]*v[i])
                    hh++;
                
                if(hh<tt)
                    dp[i][k]=dp[i-1][que[hh]]+(k-que[hh])/v[i]*w[i];
                else
                    dp[i][k]=dp[i-1][k];

            }

        }
    }
    int res=0;
    for(int i=0;i<=V;i++) res=max(res,dp[N][i]);
    cout<<dp[N][V]<<endl;
    
    
}
View Code
复制代码

 

posted @   80k  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示