单调队列优化多重背包(学习笔记)

摘要:
学习博客:https://rpdreamer.blog.luogu.org/bei-bao-wen-tif[mo+k*w[i]]=q[head]+k*c[i];这一步骤不被理解。双方同意在末尾添加a*c[i]。罗古P1776宝藏筛选#include<cstio>#include˂cstring>#include<iostream>#include˂algorithm>#include˂queu

学习博客:https://rpdreamer.blog.luogu.org/bei-bao-wen-ti

f[mo+k*w[i]]=q[head]+k*c[i];

这一步没有搞懂啊,说好的最后应该加上 a*c[i] 的呢

洛谷P1776 宝物筛选

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
typedef long long ll;

const int maxn = 100010;

int n,m,ans;
int head,tail;
int c[maxn],w[maxn],num[maxn];
int f[maxn];

int q[maxn],pos[maxn];

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}

int main(){
    n=read(),m=read();
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++){
        c[i]=read(),w[i]=read(),num[i]=read();
        if(w[i]==0){
            ans+=num[i]*c[i];
            continue;
        }
        if(num[i]>(m/w[i])) num[i]=m/w[i];
        for(int mo=0;mo<w[i];mo++){
            head=1,tail=0;
            for(int k=0;k<=(m-mo)/w[i];k++){
                int x=f[mo+k*w[i]]-k*c[i];
                while(head<=tail && q[tail]<=x) tail--;
                q[++tail]=x; pos[tail]=k;
                while(head<=tail && pos[head]<k-num[i]) head++;
                f[mo+k*w[i]]=q[head]+k*c[i];
            }
        }
    }
    
    printf("%d\n",ans+f[m]);
    
    return 0;
}

免责声明:文章转载自《单调队列优化多重背包(学习笔记)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇bootstrap-switch使用,small、mini设置B--2-基础算法(2)--二分查找扩展下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

树形DP+RMQ+单调队列(Bob’s Race HDU4123)

题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q,这些运行员的起点房间编号都是连续的,问最多可以选择多少个运动员跑步? 分析:就是给出一颗树形图,先用dp求出每个点所能经过的最远距离,然后用rmq求区间最值,...