壮哉我插头DP

jys posted @ Jul 23, 2013 01:25:56 PM in 未分类 , 1083 阅读

终于调出来了。

细节太多。。就算想清楚原理和实现细节实现出来还会有一千万个错。。

 

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <queue>
using namespace std;
int map[12][12],n,m;//m列n行 

char tmp[10];bool endofline;
std::queue<int> q[2];bool flag[2][900];
int findr[10][900],findl[10][900];

int get(int num,int i){return num&(1<<i);}
bool isleft(int num,int i){return get(num,2*i-2)>0;}
bool isright(int num,int i){return get(num,2*i-1)>0;}
bool isempty(int num,int i){return (!isleft(num,i))&&(!isright(num,i));}

int index(int x,int y){return (x-1)*m+y;}
int change(int num,int i,int v1,int v2)
{
	if((v1==1)^(get(num,2*i-2)>0))num^=(1<<(2*i-2));
	if((v2==1)^(get(num,2*i-1)>0))num^=(1<<(2*i-1));
	return num;
}
int stk[11],pos[11],top;
int zip[300000],unzip[900],tmpl[11],tmpr[11];
int f[2][900],ind;
bool check(int state)
{
	int i;
	for(i=1;i<m;i++)if(!isempty(state,i))return false;
	if(isleft(state,m)&&isright(state,m+1))return true;
	return false;
}
void updata(int from,int t)
{
	if(endofline)
	{
		if(!isempty(unzip[t],m+1))return;
		int newstate=unzip[t]<<2;
		t=zip[newstate];
	}
	f[1^ind][t]+=f[ind][from];if(!flag[1^ind][t]){q[1^ind].push(t);flag[1^ind][t]=true;}
}
void clear()
{
	memset(f,0,sizeof(f));
	memset(flag,0,sizeof(flag));
	while(!q[0].empty())q[0].pop();
	while(!q[1].empty())q[1].pop();
}
void solve()
{
	int i,j,cnt=0,state,newstate,ans=0;bool legal;
	for(j=0;j<(1<<(2*(m+1)));j++)
	{
		top=0;legal=true;
		for(i=1;i<=m+1;i++)
		{
			if(isleft(j,i)&&isright(j,i)){legal=false;break;}
			if(isleft(j,i))
			{
				stk[++top]=1;
				pos[top]=i;
			}
			else if(isright(j,i))
			{
				if(top==0||stk[top]==2){legal=false;break;}
				if(stk[top]==1)
				{
					tmpr[pos[top]]=i;
					tmpl[pos[top]]=0;
					tmpl[i]=pos[top];
					tmpr[i]=0;
					top--;
				}
			}
			else tmpl[i]=tmpr[i]=0;
			
		}
		if(top>0)legal=false;
		if(legal)
		{
			++cnt;unzip[cnt]=j;zip[j]=cnt;
			for(i=1;i<=m+1;i++){findl[i][cnt]=tmpl[i];findr[i][cnt]=tmpr[i];}
		}
		else zip[j]=0;
	}
	for(i=0;i<n;i++)
	{
		scanf("%s",tmp);
		for(j=0;j<m;j++)
			map[i+1][j+1]=(tmp[j]=='.');
	}
	n++;map[n][1]=1;map[n][m]=1;
	for(i=2;i<m;i++)map[n][i]=0;
	n++;for(i=1;i<=m;i++)map[n][i]=1;
	q[1].push(1);f[1][1]=1;
	for(i=1;i<=n;i++)for(j=1;j<=m;j++)
	{
		ind=index(i,j)&1;
		memset(flag[ind^1],0,sizeof(flag[ind^1]));
		memset(f[ind^1],0,sizeof(f[ind^1]));
		endofline=(j==m);
		while(!q[ind].empty())
		{
			state=q[ind].front();q[ind].pop();
			state=unzip[state];
			if(map[i][j]!=1)
			{
				if(isempty(state,j)&&isempty(state,j+1))
					updata(zip[state],zip[state]);
				continue;
			}
			if(i==n&&j==m)
			{
				if(check(state))ans+=f[ind][zip[state]];
				continue;
			}
			if(isempty(state,j)&&isempty(state,j+1))
			{
				newstate=change(state,j,1,0);
				newstate=change(newstate,j+1,0,1);
				updata(zip[state],zip[newstate]);
			}
			//-#
			if(isright(state,j)&&isempty(state,j+1))
			{
				updata(zip[state],zip[state]);
				newstate=change(state,j,0,0);
				newstate=change(newstate,j+1,0,1);
				updata(zip[state],zip[newstate]);
			}
			if(isleft(state,j)&&isempty(state,j+1))
			{
				updata(zip[state],zip[state]);
				newstate=change(state,j,0,0);
				newstate=change(newstate,j+1,1,0);
				updata(zip[state],zip[newstate]);
			}
			//#-
			if(isempty(state,j)&&isleft(state,j+1))
			{
				updata(zip[state],zip[state]);
				newstate=change(state,j,1,0);
				newstate=change(newstate,j+1,0,0);
				updata(zip[state],zip[newstate]);
			}
			if(isempty(state,j)&&isright(state,j+1))
			{
				updata(zip[state],zip[state]);
				newstate=change(state,j,0,1);
				newstate=change(newstate,j+1,0,0);
				updata(zip[state],zip[newstate]);
			}
			//--
			if(isright(state,j)&&isleft(state,j+1))
			{
				newstate=change(state,j,0,0);
				newstate=change(newstate,j+1,0,0);
				updata(zip[state],zip[newstate]);
			}
			if(isleft(state,j)&&isleft(state,j+1))
			{
				newstate=change(state,j,0,0);
				newstate=change(newstate,j+1,0,0);
				newstate=change(newstate,findr[j+1][zip[state]],1,0);
				updata(zip[state],zip[newstate]);
			}
			if(isright(state,j)&&isright(state,j+1))
			{
				newstate=change(state,j,0,0);
				newstate=change(newstate,j+1,0,0);
				newstate=change(newstate,findl[j][zip[state]],0,1);
				updata(zip[state],zip[newstate]);
			}
			/*
			if(isleft(state,j)&&isright(state,j+1))
				if(i==n&&j==m)ans+=f[ind][zip[state]];
			*/
		}
	}
	printf("%d\n",ans);
}
int main()
{
	while(scanf("%d %d",&n,&m)!=EOF)
	{
		if(n==0&&m==0)break;
		clear();
		solve();
	}
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter