Mondriaan's Dream
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 12854 | Accepted: 7486 |
Description
Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways.
Expert as he was in this material, he saw at a glance that he'll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won't turn into a nightmare!
Expert as he was in this material, he saw at a glance that he'll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won't turn into a nightmare!
Input
The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.
Output
For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.
Sample Input
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
Sample Output
1 0 1 2 3 5 144 51205
题目描述:
之前做过用1*2的骨牌覆盖2*n的棋盘,考虑第一个骨牌的方法,要么两个横着放,要么一个竖着放,
如果是n*m的棋盘,那么它还是可以用2*n的棋盘(每两行)递推过去的,每行(包括第一行)有三种选择,横着放,竖着放,
不放,如果用1表示横着放和竖着放的第二个,0表示竖着放的第一个和不放,每次都是两行之间的转换,
找出可以互相转换的状态就可以,采用深搜,
设pre和now,
如果当前位置横着放,状态为11,那么上一行也必须是11
如果当前位置竖着放,状态为1,上一行为0
如果当前位置不放,那么上一行此位置为1,当前位置为0
,然后从第0行全为1开始,因为这样转换之后的状态才能构成一个完整的棋盘。
#include <iostream> #include <cstdio> #include <cstring> #define maxn 12 #define LL long long using namespace std; int h,w; LL d[maxn][1<<maxn]; LL cnt; LL EX[100000000][2]; void dfs(int l,int now,int pre) { if(l>w) return ; if(l==w) { EX[cnt][0]=pre; EX[cnt++][1]=now; //cout<<pre<<" "<<now<<endl; return ; } dfs(l+2,((now<<2 )|3),((pre<<2) | 3)) ; //横放 dfs(l+1,((now<<1) |1),(pre<<1) ) ; //竖放 dfs(l+1, (now<<1) , ((pre<<1)| 1)) ; //不放 } void solve() { int s=(1<<w)-1; d[0][s]=1; for(int i=0;i<h;i++) for(int j=0;j<cnt;j++) { d[i+1][EX[j][1]]+=d[i][EX[j][0]]; } // for(int j=0;j<cnt;j++) // printf("%d %d ",EX[j][1],EX[j][0]); printf("%lld ",d[h][s]); } int main() { while(~scanf("%d%d",&h,&w) && (h!=0 && w!=0)) { memset(d,0,sizeof(d)); // if(h>w) // swap(h,w); cnt=0; dfs(0,0,0); solve(); } return 0; }