ZCMU—1159

来源:互联网 发布:赵薇 利益集团 知乎 编辑:程序博客网 时间:2024/06/05 17:19

1159: Tiling a Grid With Dominoes

Time Limit: 1 Sec  Memory Limit: 128 MB
[Submit][Status][Web Board]

Description

We wish to tile a grid 4 units high and N units long with rectangles (dominoes) 2 units by one unit (in either orientation). For example, the figure shows the five different ways that a grid 4 units high and 2 units wide may be tiled.

Write a program that takes as input the width, W, of the grid and outputs the number of different ways to tile a 4-by-W grid.

Input

The first line of input contains a single integer N, (1 ≤ N ≤ 1000) which is the number of datasets that follow.
Each dataset contains a single decimal integer, the width, W, of the grid for this problem instance.

Output

For each problem instance, there is one line of output: The problem instance number as a decimal integer (start counting at one), a single space and the number of tilings of a 4-by-W grid. The values of W will be chosen so the count will fit in a 32-bit integer.

Sample Input

3
2
1
2

Sample Output

1 5
2 1
3 5

【分析】

骨牌覆盖加强版....继2*N和3*N的棋盘之后的4*N的棋盘....因为有4*N的基数太大,直接dp肯定会超时。所以考虑状态压缩,这种题目的状态压缩还是比较好理解的,因为对于棋盘上的位置只有0和1表示这个位置被覆盖或没有被覆盖
对于铺砖问题。我们可以一行一行的分析即一行一行的铺。由于只有1*2的砖。所以当前处理行只会受到上一行的影响。上上行肯定会被影响...所以对于当前处理行的状态第i位为1表示第i个位置会占用下一行的位置。即砖是竖着放的。0表示不占用下一行的位置。0肯定是成对出现的。因为横放的话需要两个位置。分析到这里后。
基本算法就出来了。用dp[i][j]表示处理完前i行。第i行状态为j的方法数。
j为01序列的十进制表示。然后我们可以根据j用dfs构造出一个可行状态ss。那么dp[i+1][ss]+=dp[i][j]。所以我们只需要枚举第i行状态推i+1行就可以了。最后只要输出dp[N][0]就行了。因为最后一行不能占用下一行的位置了。
这里可以做一个预处理,因为dp[i][j]这个数组内容不会因为N的影响而造成影响,所以可以先把dp这个数组给算出来。

【代码】
#include <stdio.h>#include <string.h>int dp[30][30];void dfs(int s,int ss,int p,int dep){      if(p>3)    {          dp[dep+1][ss]+=dp[dep][s];          return;      }      if(s&(1<<p))          dfs(s,ss,p+1,dep);      else      {          dfs(s,ss|(1<<p),p+1,dep);          if(p<=2&&!(s&(1<<(p+1))))              dfs(s,ss,p+2,dep);      }  }  int main()  {      int i,j,n,t,cas=1;      memset(dp,0,sizeof dp);      dp[0][0]=1;      for(i=0;i<25;i++)          for(j=0;j<16;j++)              if(dp[i][j])                  dfs(j,0,0,i);      scanf("%d",&t);      while(t--)      {          scanf("%d",&n);          printf("%d %d\n",cas++,dp[n][0]);      }      return 0;  }  


0 0
原创粉丝点击