单调队列优化多重背包 洛谷P1776 宝物筛选

泄露秘密 提交于 2019-11-27 07:12:21

题目链接:https://www.luogu.org/problem/P1776

单调队列,就是在区间移动时动态维护区间的最值

看了蛮久还是蛮晕的,看不太明白,因为单调队列和多重背包都很不熟,不想继续在这个知识点上浪费时间了,就先记住模板吧,之后题做多了,写题时遇到了,多多温习。

看的几篇博客:https://blog.csdn.net/qq_40679299/article/details/81978770

https://www.cnblogs.com/-guz/p/9866118.html

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=1<<30;
const int maxn=4e4+7;
int dp[maxn],q[maxn],p[maxn];
int main(){
    int n,W;cin>>n>>W;
    int ans=0;
    for(int i=1;i<=n;i++){
        int v,w,num;scanf("%d%d%d",&v,&w,&num);
        if(w==0)ans+=v*num;
        num=min(W/w,num);//最大能够承载的该物品的数量 
        for(int d=0;d<w;d++){//枚举重量的余数 
            int head=0,tail=0;
            int k=(W-d)/w;//我们转换后的表达式为dp[d+k*w]-k*v,所有我们要保证d+k*w<=W 
            for(int j=0;j<=k;j++){
                while(head<tail&&dp[d+j*w]-j*v>=q[tail-1])tail--;
                q[tail]=dp[d+j*w]-j*v;p[tail++]=j;
                while(head<tail&&p[head]<j-num)head++;
                dp[d+j*w]=max(dp[d+j*w],q[head]+j*v);
            } 
        }
    }
    cout<<dp[W]+ans<<endl;
    return 0;
} 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!