openjudge完美覆盖

1665:完美覆盖

  • 查看
  • 提交
  • 统计
  • 提问
总时间限制: 
1000ms 
内存限制: 
65536kB
描述
一张普通的国际象棋棋盘,它被分成 8 乘 8 (8 行 8 列) 的 64 个方格。设有形状一样的多米诺牌,每张牌恰好覆盖棋盘上相邻的两个方格,即一张多米诺牌是一张 1 行 2 列或者 2 行 1 列的牌。那么,是否能够把 32 张多米诺牌摆放到棋盘上,使得任何两张多米诺牌均不重叠,每张多米诺牌覆盖两个方格,并且棋盘上所有的方格都被覆盖住?我们把这样一种排列称为棋盘被多米诺牌完美覆盖。这是一个简单的排列问题,同学们能够很快构造出许多不同的完美覆盖。但是,计算不同的完美覆盖的总数就不是一件容易的事情了。不过,同学们 发挥自己的聪明才智,还是有可能做到的。
现在我们通过计算机编程对 3 乘 n 棋盘的不同的完美覆盖的总数进行计算。



任务
对 3 乘 n 棋盘的不同的完美覆盖的总数进行计算。
输入
一次输入可能包含多行,每一行分别给出不同的 n 值 ( 即 3 乘 n 棋盘的列数 )。当输入 -1 的时候结束。

n 的值最大不超过 30.
输出
针对每一行的 n 值,输出 3 乘 n 棋盘的不同的完美覆盖的总数。
样例输入
2
8
12
-1
样例输出
3
153
2131
思路一:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[50][1<<4];
int i,j,num,n;
void dfs(int x,int d,int len)
{
   if (len>=3)
    {
    	f[x][d]+=num; return ;
    }
   dfs(x,d,len+1);
   if (len<=1&&(d&1<<len)==0&&(d&1<<(len+1))==0)
    dfs(x,d|1<<len|1<<(len+1),len+2);
}
int main()
{
	scanf("%d",&n);
	while (n!=-1)
	 {
	 	memset(f,0,sizeof(f));
	 	num=1;
	 	f[0][(1<<3)-1]=1;//这里要注意,如果没有处理0的话就会wa
	 	dfs(1,0,0);
	 	for (i=2;i<=n;i++)
	 	 {
	 	 	 for (j=0;j<=(1<<3)-1;j++)
	 	 	  {
	 	 	  	if (f[i-1][j]!=0)
	 	 	  	 num=f[i-1][j];
	 	 	  	else
			     continue;
				dfs(i,~j&((1<<3)-1),0); 
	 	 	  }
	 	 }
	 	printf("%d\n",f[n][(1<<3)-1]);
        scanf("%d",&n);
	 }
}//状态压缩型动态规划
思路二:

     
     
     
     
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,f[50];
int main()
{
f[0]=1;f[2]=3;
for (int i=4;i<=30;i+=2)
{
f[i]=f[i-2];
for (int j=i-2;j>=0;j-=2)
  f[i]+=2*f[j];
}
while ((scanf("%d",&n)==1)&&(n!=-1))
  printf("%d\n",f[n]);
return 0;
}
//把每两列看作一个整体,每两列有三种放置方法,所以f[i-2]×3,再往前推可以把所以同一组横放的两个改成那个竖放。

你可能感兴趣的:(openjudge完美覆盖)