HDU 1992 Tiling a Grid With Dominoes (状压 dp)

Problem 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 3 7
 

Sample Output
  
  
1 5 2 11 3 781
 

一个地点为 1 代表是放着竖着向下的砖


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>


#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)

#define eps 1e-8

#define fre(i,a,b)  for(i = a; i <b; i++)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define bug         pf("Hi\n")

using namespace std;

#define INF 0x3f3f3f3f
#define N 22

int dp[N][16];

void dfs(int dep,int up,int down,int pos)     //第 dep行状态为 up 更新下一行状态为 down 的情况
{
	if(pos>3)
	{
		dp[dep+1][down]+=dp[dep][up];
		return ;
	}

	if(up&(1<<pos))                       //上一行对下一行的pos位置填满
	{
		 dfs(dep,up,down,pos+1);
	     return ;
	}
                                          
	dfs(dep,up,down|(1<<pos),pos+1);      //竖着放在dep+1层的pos位置一个竖着向下的砖
	if(pos<=2&&!(up&(1<<(pos+1))))        //横着放一块砖,占据两个位置
		 dfs(dep,up,down,pos+2);

}

int main()
{
	int i,j,t,ca=0;
	dp[0][0]=1;

	fre(i,0,N)
	 fre(j,0,16)
	   if(dp[i][j])
		 dfs(i,j,0,0);

	sf(t);
	while(t--)
	{
		sf(i);
		pf("%d %d\n",++ca,dp[i][0]);
	}
	return 0;
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值