这道题就是道状压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 ",ans); return 0; }