0
点赞
收藏
分享

微信扫一扫

Long Dominoes (状态dp)


Find the number of ways to tile an m*n rectangle with long dominoes -- 3*1 rectangles.

Each domino must be completely within the rectangle, dominoes must not overlap (of course, they may touch each other), each point of the rectangle must be covered.


Input

The input contains several cases. Each case stands two integers m and n (1 <= m <= 9, 1 <= n <= 30) in a single line. The input ends up with a case of m = n = 0.

<p< dd="">

Output

Output the number of ways to tile an m*n rectangle with long dominoes.


<p< dd="">

Sample Input


3 3
3 10
0 0


<p< dd="">

Sample Output

 

2
28



题目大概:

用1*3的矩形把n*m的矩形放满,有多少种方法。


思路:

和第一个状态dp一样的题。


代码:


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
const int le=9;
ll dp[31][1<<le][1<<le];
int w,h;
int pan(int pos,int qian,int qian1)//判断状态是否合法
{
for(int i=pos;i<pos+3;i++)
{
if(!(qian&(1<<i))||!(qian1&(1<<i)))
return 0;
}
return 1;
}
void dfs(int pos,int st,int now,int qian,int qian1,ll sum)
{
if(pos==w)
{
dp[st][now][qian]+=sum;
return;
}
if(pos+3<=w&&pan(pos,qian,qian1))//横放
{
dfs(pos+3,st,now|(1<<pos)|(1<<(pos+1))|(1<<(pos+2)),qian,qian1,sum);

}
if(!(qian&(1<<pos))&&!(qian1&(1<<pos)))//竖放
{
dfs(pos+1,st,now|(1<<pos),qian|(1<<pos),qian1,sum);
}
if(qian1&(1<<pos))//不放
{
dfs(pos+1,st,now,qian,qian1,sum);
}
}
int main()
{
while(~scanf("%d%d",&w,&h)&&(w||h))
{
memset(dp,0,sizeof(dp));
dfs(0,1,0,(1<<w)-1,(1<<w)-1,1);
for(int i=2;i<=h;i++)//枚举行
{
for(int j=0;j<(1<<w);j++)//枚举每一个状态
{
for(int k=0;k<(1<<w);k++)//枚举上一行状态
{
if(dp[i-1][j][k])
dfs(0,i,0,j,k,dp[i-1][j][k]);
}
}
}
printf("%lld\n",dp[h][(1<<w)-1][(1<<w)-1]);
}

return 0;
}



举报

相关推荐

0 条评论