现在的位置: 首页 > 综合 > 正文

Hexagon and Rhombic Dominoes zoj2673

2013年12月02日 ⁄ 综合 ⁄ 共 1626字 ⁄ 字号 评论关闭

从昨天下午写到现在,终于算是A了,实在是很郁闷啊!

这道题看到能想到的就是状态压缩dp了,刚开始写了一个很暴力的,开了两个数组,dp1[i][j]用来记录第i行头朝上的,dp2[i][j]用来记录第i行头朝下的,然后位运算按照条件进行dp的,超时就不用说了,但是一直wa就让我很郁闷啊!!改了一个晚上,还是那样,然后看了别人的题解说只开一个数组只记录头朝下的进行判断,然后又写但是只解决了超时的问题,然后的然后,想想换个记录三角形头朝上的,因为那样最后求了一半的时候合起来比较好判断,然后竟然ac啦!高兴啊,但是那个为什么错就不知道了。。。

思路:dp[i][j]用来记录第i行三角形头朝上状态为j的一共的个数,dp[i][j]+=dp[i-1][k]如果状态j和上一行的状态k相容,在这里我是用一个函数进行判断的,是将数据拆成一位一位的然后进行判断。最后sum+=dp[2*n][i]*dp[2*n][i];因为上面的半边合下面的半边完全相同,就可以直接简化了,下面是代码!

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
#include<map>
using namespace std;

#define rep(i,n) for(int i=0; i<n; i++)
#define repf(i,n,m) for(int i=(n); i<=(m); ++i)
#define repd(i,n,m) for(int i=(n); i>=(m); --i) 
#define ll long long
#define arc(a) ((a)*(a))
#define inf 100000
#define exp 0.000001
#define N  1<<13
ll dp[20][N];

bool fun(int n,int x,int y)
{ 
	int sign=-1;//sign用来记录这一位的前一个状态的。 
	int flag=true;
	rep(i,n)
	{
        int m=(y>>i)&1; 
		if(m==1 && sign==-1)
		{
			sign=(x>>i)&1;
			if(i==n-1 || sign==0) flag=false;
			sign=-1;
		}
		else if(m==1 && sign==1)
		{
			sign=(x>>i)&1;
		}
		else if(m==1 && sign==0)
		{
             sign=(x>>i)&1;
             if(sign==0 || i==n-1) flag=false;
             sign=-1;
        }
		else if(m==0 && sign==-1)
		{
			sign=(x>>i)&1;
		}
		else if(m==0 && sign==1)
		{
              flag=false;
		}
		else if(m==0 && sign==0)
			sign=(x>>i)&1;
		if(flag==false)
			return flag;
	}
	return true;
}

int main()
{ 
	int n;
	int test=0;
	while(cin>>n)
	{
       if(test!=0) printf("\n");
       test++;
		memset(dp,0,sizeof(dp)); 
		dp[n][(1<<n)-1]=1;
		repf(i,n+1,2*n)
		{ 
			rep(j,1<<(i-1))//shang
			{ 
				if(dp[i-1][j]==0) continue;
		        rep(k,1<<i)//下
                {  
					if(fun(i,j,k))//判断两种状态是否相容 
					{ 
						dp[i][k]+=dp[i-1][j];
                     }
                  }
			} 
		}
		ll sum=0;
		rep(i,1<<(2*n))
		 rep(j,1<<(2*n))
		  if((i^j)==0)
		 sum+=dp[2*n][i]*dp[2*n][j]; //求到一半直接简化 
		cout<<sum<<endl;
	}
   return 0;
}
  

抱歉!评论已关闭.