2/13 复习下背包+单调队列变型

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2/13 复习下背包+单调队列变型相关的知识,希望对你有一定的参考价值。

回过头来看这些背包和贪心,发现简单了不少……qaq

简单的01背包求方案数:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e4+5;;
int v,n,a[30],f[maxn];

signed main()

    scanf("%lld%lld",&v,&n);
    for(int i=1;i<=v;i++)
        scanf("%lld",&a[i]);
    f[0]=1;
    for(int i=1;i<=v;i++)
    
        for(int j=a[i];j<=n;j++)
            f[j]=f[j]+f[j-a[i]];
    
    cout<<f[n]<<endl;
    return 0;


https://www.luogu.com.cn/problem/P1586
多增加了一个维度:用到了几个数构成了这个结果

f[i][j]:表示数字i用了j个数构成
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
const int M=32768;
int t,n,f[maxn][5];

signed main()

    f[0][0]=1;
    for(int i=1;i*i<=M;i++)
    
        for(int j=i*i;j<=M;j++)
        
            for(int k=1;k<=4;k++)
                f[j][k]+=f[j-i*i][k-1];
        
    
    scanf("%lld",&t);
    while(t--)
    
        int n,tmp=0;
        scanf("%lld",&n);
        for(int i=1;i<=4;i++)
            tmp+=f[n][i];
        cout<<tmp<<endl;
    
    return 0;

https://www.luogu.com.cn/problem/P1638
不断更新左端点的值,就是左端点最后出现的位置如果大于左端点,则left++

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
int pos[2005],p[maxn],n,m,k;

signed main()

    scanf("%lld%lld",&n,&m);
    memset(pos,-1,sizeof(pos));
    int l=1,ll=0,rr=0,ml=inf;
    for(int i=1;i<=n;i++)
    
        scanf("%lld",&p[i]);
        if(pos[p[i]]==-1)
            k++;
        pos[p[i]]=i;
        while(l!=i&&l<pos[p[l]])
            l++;
        if(k==m&&i-l+1<ml)
        
            ml=i-l+1;
            ll=l;
            rr=i;
        
    
    //cout<<ml<<endl;
    cout<<ll<<" "<<rr<<endl;
    return 0;

以上是关于2/13 复习下背包+单调队列变型的主要内容,如果未能解决你的问题,请参考以下文章

背包问题入门(单调队列优化多重背包

01背包+完全背包+多重背包+单调队列

单调队列优化多重背包

单调队列优化DP,多重背包

单调队列优化多重背包

单调队列优化多重背包