【jzoj5322】【GDOI2017模擬8.21】【小朋友】【狀態壓縮動態規劃】

description

這裏寫圖片描述

solution

可以發現三人桌不會超過3個,設f[i][j][s]表示到第i個人,用了j個3人桌,往前k+1個人選取狀態爲s。每個狀態最前的位爲1就一定要安排一桌,暴力枚舉即可,到了最後i要枚舉到n+k+1,n以後的不算貢獻,但是要保證n-k到n的人都被選完。

code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
#define fo(i,j,k) for(LL i=j;i<=k;i++)
#define fd(i,j,k) for(LL i=j;i>=k;i--)
#define fr(i,j) for(LL i=begin[j];i;i=next[i])
using namespace std;
LL const mn=1000+13,inf=1e18+7;
LL n,K,a[mn],b[mn],f[mn][5][2050],g[mn][5][2050],h[mn][5][2050];
LL min(LL x,LL y){
    return (x<y)?x:y;
}
int main(){
    freopen("friends.in","r",stdin);
    freopen("friends.out","w",stdout);
    scanf("%lld%lld",&n,&K);K++;
    fo(i,1,n)scanf("%lld",&a[i]);
    LL tmp=((n-1)/4+1)*4-n,mx=(1<<K)-1;
    fo(i,0,n+K)fo(j,0,tmp)fo(s,0,mx)f[i][j][s]=inf;
    f[0][0][0]=0;
    fo(i,1,n+K)fo(j,0,tmp)fo(s,0,mx)if(((i<=n)&&(s&1))||((i>n)&&(!(s&1)))){
        f[i][j][s]=f[i-1][j][s>>1];
        g[i][j][s]=s>>1;
        h[i][j][s]=0;
        if(i-K>0)fd(ii,K,2)if((i-ii+1<=n)&&(!(s&(1<<(ii-1))))&&(i-K<=n))
            fd(jj,ii-1,2)if((!(s&(1<<(jj-1))))&&(i-jj+1<=n)){
            if(j){
                LL tm2=(a[i-K]+a[i-ii+1]+a[i-jj+1])*4,
                    tm3=pow(a[i-K]*12-tm2,2)+pow(a[i-ii+1]*12-tm2,2)+pow(a[i-jj+1]*12-tm2,2),
                    tm4=f[i][j][s];
                f[i][j][s]=min(f[i][j][s],f[i-1][j-1][(s>>1)+(1<<(K-1))+(1<<(ii-2))+(1<<(jj-2))]+tm3);
                if(f[i][j][s]!=tm4)g[i][j][s]=(s>>1)+(1<<(K-1))+(1<<(ii-2))+(1<<(jj-2)),h[i][j][s]=-1;
            }
            fd(kk,jj-1,2)if((!(s&(1<<(kk-1))))&&(i-kk+1<=n)){
                LL tm2=(a[i-K]+a[i-ii+1]+a[i-jj+1]+a[i-kk+1])*3,
                    tm3=pow(a[i-K]*12-tm2,2)+pow(a[i-ii+1]*12-tm2,2)+pow(a[i-jj+1]*12-tm2,2)+pow(a[i-kk+1]*12-tm2,2),
                    tm4=f[i][j][s];
                f[i][j][s]=min(f[i][j][s],f[i-1][j][(s>>1)+(1<<(K-1))+(1<<(ii-2))+(1<<(jj-2))+(1<<(kk-2))]+tm3);
                if(f[i][j][s]!=tm4)g[i][j][s]=(s>>1)+(1<<(K-1))+(1<<(ii-2))+(1<<(jj-2))+(1<<(kk-2)),h[i][j][s]=0;
            }
        }
    }
    printf("%lld\n",f[n+K][tmp][0]);
    LL j=tmp,s=0,tm2=1;
    fd(i,n+K,1){
        if(g[i][j][s]!=(s>>1)){
            if(h[i][j][s]==-1){
                b[i-K]=tm2;
                fd(ii,K,2)if((!(s&(1<<(ii-1))))&&(g[i][j][s]&(1<<(ii-2))))
                    fd(jj,ii-1,2)if((!(s&(1<<(jj-1))))&&(g[i][j][s]&(1<<(jj-2))))b[i-ii+1]=b[i-jj+1]=tm2;
            }else{
                b[i-K]=tm2;
                fd(ii,K,2)if((!(s&(1<<(ii-1))))&&(g[i][j][s]&(1<<(ii-2))))
                    fd(jj,ii-1,2)if((!(s&(1<<(jj-1))))&&(g[i][j][s]&(1<<(jj-2))))
                        fd(kk,jj-1,2)if((!(s&(1<<(kk-1))))&&(g[i][j][s]&(1<<(kk-2))))b[i-ii+1]=b[i-jj+1]=b[i-kk+1]=tm2;
            }
            tm2++;
        }
        LL tm3=j+h[i][j][s],tm4=g[i][j][s];
        j=tm3;s=tm4;
    }
    fo(i,1,n)printf("%lld ",b[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章