洛谷金秋夏令营模拟赛 第2场 T11737 时之终末

这道题就是道状压dp...比赛的时候太贪心 然后状压又不好 所以T2 T3一起挂了QAQ 吸取教训QAQ

f[i][j][k]表示前i个数选了j个 最后a个的状态为k的答案

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using std::swap;
const int M=157;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int n,m,a,b,k,ly;
int v[M],sz[M];
int f[2][55][70007],y,w[7007],val[70007],ans;
int max(int a,int b){return a>b?a:b;}
void maxs(int&a,int b){if(a<b) a=b;}
int main(){
    n=read(); m=read(); a=read(); b=read();
    for(int i=1;i<=n;i++) v[i]=read();
    for(int i=1;i<=b;i++){
        k=read(); y=read();
        int s=0;
        for(int j=1;j<=k;j++) ly=read(),s|=(1<<(a-ly));
        w[s]+=y;
    }
    int now=0,last=1,tot=1<<a;
    for(int i=0;i<tot;i++) for(int x=i;x;x=(x-1)&i) val[i]+=w[x];
    memset(f[now],-0x3f,sizeof(f[now]));
    for(int s=0;s<tot;s++){
        int x=val[s];
        int sz=0;
        for(int i=0;i<a;i++)if((s>>i)&1) sz++,x+=v[a-i];
        f[now][sz][s]=x;
    } 
    for(int i=a+1;i<=n;i++){
        swap(now,last);
        memset(f[now],-0x3f,sizeof(f[now]));
        for(int j=0;j<=m;j++)
        for(int s=0;s<tot;s++)
        maxs(f[now][j+(s&1)][s],max(f[last][j][s>>1],f[last][j][s>>1|1<<(a-1)])+val[s]+(s&1)*v[i]);
    }
    for(int s=0;s<(1<<a);s++) for(int j=0;j<=m;j++) maxs(ans,f[now][j][s]);
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2017-10-05 13:56  友人Aqwq  阅读(218)  评论(0编辑  收藏  举报