1. 程式人生 > >洛谷金秋夏令營模擬賽 第2場 T11737 時之終末

洛谷金秋夏令營模擬賽 第2場 T11737 時之終末

() 技術 style fine bsp cst ++ 個數 +=

這道題就是道狀壓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

洛谷金秋夏令營模擬賽 第2場 T11737 時之終末