ZOJ 3466 插头dp

来源:互联网 发布:第三方支付有哪些 知乎 编辑:程序博客网 时间:2024/06/10 01:59
做这题时直接在上一道题上修改的。
http://blog.csdn.net/chm517/article/details/9968775
还是多条回路的插头dp,四边形改成六边形,需要自己重推。
up,left->up1,up2,left
每个点依旧是两个插头。



#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>typedef long long LL;using namespace std;const int N=16;const int HASH=15511;const int STATE=1000000;LL ans;int n,m,mm;int map[N][N];int ex,ey;struct HASHMAP{    int head[HASH],next[STATE],size;    int state[STATE];    LL f[STATE];    void init()    {        size=0;        memset(head,-1,sizeof(head));    }    void push(int st,LL ans)    {        int i;        int h=st%HASH;        for(i=head[h];i!=-1;i=next[i])          if(state[i]==st)          {              f[i]+=ans;              return;          }        state[size]=st;        f[size]=ans;        next[size]=head[h];        head[h]=size++;    }}hm[2];void shift(int cur){    for(int i=0;i<hm[cur].size;i++)         hm[cur].state[i]<<=1;}inline int cp(int p,int i){    return p&(~(1<<i));}inline int cp(int p,int i,int j){    return p&(~(1<<i))&(~(1<<j));}inline int cp(int p,int i,int j,int k){    return p&(~(1<<i))&(~(1<<j))&(~(1<<k));}inline int getp(int p,int i){    return 1&(p>>i);}inline int pp(int i,int k){   return k<<i;}void dp(int i,int j,int cur){   int jj=j*2+i%2;    int tt=i%2==0?-1:0;       for(int k=0;k<hm[cur].size;k++)        {int s=hm[cur].state[k];         LL data=hm[cur].f[k];         int left=getp(s,jj);         int up1=getp(s,jj+1);         int up2=getp(s,jj+2);      int add=left+up1+up2;         if (add==0)            {if (j+tt>=0)                if (map[i+1][j+tt]&&map[i+1][j+tt+1])                   hm[cur^1].push(s|pp(jj,1)|pp(jj+1,1),data);             if (map[i+1][j+tt+1]&&map[i][j+1])                   hm[cur^1].push(s|pp(jj+1,1)|pp(jj+2,1),data);             if (j+tt>=0)                if (map[i+1][j+tt]&&map[i][j+1])                  hm[cur^1].push(s|pp(jj,1)|pp(jj+2,1),data);             continue;            }         if (add==1)            {int tmp=cp(s,jj,jj+1,jj+2);             if (j+tt>=0)               if (map[i+1][j+tt]) hm[cur^1].push(tmp|pp(jj,1),data);             if (map[i+1][j+tt+1]) hm[cur^1].push(tmp|pp(jj+1,1),data);             if (map[i][j+1]) hm[cur^1].push(tmp|pp(jj+2,1),data);             continue;            }         if (add==2)            {hm[cur^1].push(cp(s,jj,jj+1,jj+2),data);             if (i==ex&&j==ey) ans+=data;             continue;            }        }}char str[5];void init(){   int x,y;    memset(map,0,sizeof(map));    n=8;    ex=-1;    for (int i=0;i<n;i++)        for(int j=0;j<m;j++)             map[i][j]=1;    while (mm--)        {   scanf("%s",str);            x=str[0]-'A';            y=str[1]-'A';            map[y][m-1-x]=0;        }    for (int i=0;i<n;i++)        for(int j=0;j<m;j++)             if (map[i][j]) {ex=i; ey=j;}}void solve(){    int cur=0;    ans=0;    hm[cur].init();    hm[cur].push(0,1);    for(int i=0;i<n;i++)        {for(int j=0;j<m;j++)            if (map[i][j])            {             hm[cur^1].init();             dp(i,j,cur);             cur^=1;            }          shift(cur);        }    printf("%lld\n",ans);}int main(){    while(scanf("%d%d",&m,&mm)!=EOF)    {        init();        if(ex==-1)        {            printf("1\n");            continue;        }        solve();    }    return 0;}


原创粉丝点击