bzoj 1187 [HNOI2007]神奇游乐园

插头dp;参考cdq的论文;
感觉模仿po姐先把状态转移写出来,会更加清晰好调;
注意情况分类,与换行时的小讨论;

/**************************************************************
    Problem: 1187
    User: jiazihankk
    Language: C++
    Result: Accepted
    Time:56 ms
    Memory:2976 kb
****************************************************************/

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=(n);i++)
#define rep2(i,k,n) for(int i=k;i>=(n);i--)
#define inf 0x7f7f7f7f 
using namespace std;
const int N=30000;
int A[105][10],g[N],ans[N],Ans=-inf,n,m,S,state[N],tot=0;
vector<pair<int,bool> > trans[7][1<<14];
inline int press(int b[]){
    int ret=0;rep(i,0,m)ret|=b[i]<<(2*i);return ret;
}
inline void antipress(int x){
    static int a[10];
    rep(i,0,m)a[i]=(x>>(i*2))&3;
    rep(i,0,m)printf("%d ",a[i]);
}
void Cal(int x){
    static int a[10],b[10],sta[10],p[10];
    int top=0;
    rep(i,0,m)a[i]=(x>>(i*2))&3;
    rep(i,0,m){
        if(a[i]==3)return;
        if(!a[i])continue;
        if(a[i]==1)sta[++top]=i;
        else{if(!top)return;
        p[sta[top]]=i;p[i]=sta[top];
        sta[top--]=0;
        }
    }
    if(top)return;
    state[++tot]=x;
    rep(i,1,m){
        switch(a[i-1]<<2|a[i]){
            case 0<<2|0:{
                memcpy(b,a,sizeof(a));
                trans[i][x].push_back(pair<int,bool>(press(b),false));
                b[i-1]=1;b[i]=2;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
                }
            case 1<<2|0:{
                memcpy(b,a,sizeof(a));
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                b[i-1]=0;b[i]=1;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
            case 0<<2|1:{
                memcpy(b,a,sizeof(a));
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                b[i-1]=1;b[i]=0;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
            case 1<<2|1:{
                memcpy(b,a,sizeof(a));
                b[i-1]=0,b[i]=0,b[p[i]]=1;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
            case 2<<2|2:{
                memcpy(b,a,sizeof(a));
                b[i-1]=0,b[i]=0,b[p[i-1]]=2;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
            case 2<<2|1:{
                memcpy(b,a,sizeof(a));
                b[i-1]=0;b[i]=0;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
            case 1<<2|2:{
                memcpy(b,a,sizeof(a));
                b[i-1]=b[i]=0;
                if(press(b)==0)
                trans[i][x].push_back(pair<int,bool>(-1,true));
                break;
            }
            case 0<<2|2:{
                memcpy(b,a,sizeof(a));
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                b[i-1]=2;b[i]=0;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
            case 2<<2|0:{
                memcpy(b,a,sizeof(a));
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                b[i-1]=0;b[i]=2;
                trans[i][x].push_back(pair<int,bool>(press(b),true));
                break;
            }
        }
    }
}  //left to down up to left
int main(){//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
vector<pair<int,bool> > :: iterator it;
    scanf("%d%d",&n,&m);
    S=1<<((m+1)*2);

    rep(i,0,S-1)
     Cal(i);

 // rep(i,1,tot)antipress(state[i]);
    rep(i,1,n)rep(j,1,m)
    scanf("%d",&A[i][j]);
     memset(ans,-0x7f,sizeof(ans));
    memset(g,-0x7f,sizeof(g));
    ans[0]=0;

/*  
    rep(j,1,m){
        printf("%d\n",j);
    rep(k,1,tot){
    int tmp=state[k];
    for(it=trans[j][tmp].begin();it!=trans[j][tmp].end();++it){
        antipress(tmp);printf("--->");if(it->first==-1)printf("Ans");else antipress(it->first);
        printf("\n");
    }
}
}*/
rep(i,1,n){
    rep(j,1,m){
        rep(k,1,tot)
        if(ans[state[k]]>-inf)
        {int tmp=state[k];
            for(it=trans[j][tmp].begin();it!=trans[j][tmp].end();it++){
                int ccc=it->first;
                int& val=it->first!=-1 ? g[it->first] : Ans;
                int cc=ans[tmp]+(it->second ? 1 : 0)*A[i][j];
                val=max(val,cc);
            }   
        }
        if(j!=m)rep(k,1,tot)ans[state[k]]=g[state[k]];
        else {rep(k,1,tot)ans[state[k]]=-inf;    //
        rep(k,1,tot)if(!(state[k]>>(2*m)))ans[state[k]<<2]=g[state[k]];   //
        }
        rep(k,1,tot)g[state[k]]=-inf;
    }
}
    printf("%d",Ans);    
    return 0;
}


A掉也是有些激动呢T^T

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值