CF1316E Team Building
阿新 • • 發佈:2021-11-01
貪心+狀壓
考慮到球隊人數很小,狀壓列舉球隊每個位置,\(f_{i,j}\)表示dp到i人,球隊組成為j的最大值
由於要使貢獻最大,可以先按照\(b_i\)降序,然後每次轉移時,若選這個人,加入球隊,否則若啦啦隊沒滿,就放進啦啦隊
由於沒有使用貪心而強行列舉\(b_i\)最大的p+k裡的球隊人數,導致複雜度多個p而卡了許久
#include<bits/stdc++.h> using namespace std; const long long inf=-1e14; const int N=1e5+11; struct ab_{ int a[8],b; }sx[N]; int n,p,k; long long f[N][128]; inline int read() { int s=0; char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') { s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s; } inline void max_(long long &a,long long b){if(a<b)a=b;return;} bool cmp1(ab_ a,ab_ b){return a.b>b.b;} bool cmp2(ab_ a,ab_ b){return a.b<b.b;} int js(int x){int sum=0;while(x){x-=(x&-x);++sum;}return sum;} signed main() { n=read(); p=read(); k=read(); for(int i=1;i<=n;++i) sx[i].b=read(); for(int i=1;i<=n;++i) for(int j=1;j<=p;++j) sx[i].a[j]=read(); sort(sx+1,sx+n+1,cmp1); long long sum=0; int M=(1<<p)-1; for(int i=1;i<=p+k;++i) sum+=sx[i].b; for(int i=1;i<=p+k;++i) for(int j=1;j<=p;++j) sx[i].a[j]-=sx[i].b; for(int i=0;i<=n;++i) for(int j=0;j<=M;++j) f[i][j]=inf; f[0][0]=0; if(p+k==n) { for(int i=1;i<=n;++i) { for(int j=0;j<M;++j) for(int h=1;h<=p;++h) if(!((1<<h-1)&j)) max_(f[i][j|(1<<h-1)],f[i-1][j]+sx[i].a[h]); for(int j=0;j<=M;++j) max_(f[i][j],f[i-1][j]); } cout<<sum+f[n][M]<<endl; return 0; } long long ans=0; for(int i=0;i<=p+k;++i) for(int j=0;j<=M;++j) f[i][j]=inf; f[0][0]=0; for(int i=1;i<=p+k;++i) { for(int j=0;j<M;++j) for(int h=1;h<=p;++h) if(!((1<<h-1)&j)) max_(f[i][j|(1<<h-1)],f[i-1][j]+sx[i].a[h]); for(int j=0;j<=M;++j) max_(f[i][j],f[i-1][j]); } ans=f[p+k][M]+sum; for(int g=1;g<=p;++g) { sum-=sx[p+k-g+1].b; for(int i=1;i<=p;++i) sx[p+k-g+1].a[i]+=sx[p+k-g+1].b; memset(f,-0x3f,sizeof(f)); f[p+k-g][0]=0; for(int i=p+k-g+1;i<=n;++i) { for(int j=0;j<M;++j) { if(js(j)>g) continue; if(f[i-1][j]<inf) continue; for(int h=1;h<=p;++h) if(!((1<<h-1)&j)) max_(f[i][j|(1<<h-1)],f[i-1][j]+sx[i].a[h]); } for(int j=0;j<=M;++j) max_(f[i][j],f[i-1][j]); } f[0][0]=0; for(int i=1;i<=p+k-g;++i) { for(int j=0;j<M;++j) { if(js(j)>p-g) continue; if(f[i-1][j]<inf) continue; for(int h=1;h<=p;++h) if(!((1<<h-1)&j)) max_(f[i][j|(1<<h-1)],f[i-1][j]+sx[i].a[h]); } for(int j=0;j<=M;++j) max_(f[i][j],f[i-1][j]); } for(int i=0;i<=M;++i) { if(js(i)!=g)continue; max_(ans,f[p+k-g][M-i]+f[n][i]+sum); } } cout<<ans<<endl; return 0; }