http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1563
Long Dominoes
Time Limit: 2000 msMemory Limit: 65536 KB
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.
Output
Output the number of ways to tile an m*n rectangle with long dominoes.
Sample Input
3 3 3 10 0 0
Sample Output
2 28
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> using namespace std; long long temp; long long height,width; long long dig[20]; long long st[10] ; long long dp[33][20000]; void change(int n) { memset(dig,0,sizeof(dig)); int k = 0; while(n) { dig[k++]=n%3; n/=3; } } void init() { st[0]=1; for(int i=1;i<10;i++) st[i]=st[i-1]*3; }//{1,3,9,27......} void dfs(int i,int s,int col,long long tem) { if(col==width){ dp[i][s]+= tem; return ; } if(dig[col]==0) { if(col+2<width&&dig[col+1]==0&&dig[col+2]==0) dfs(i,s,col+3,tem); dfs(i,s+2*st[col],col+1,tem); } else if(dig[col]==1) { dfs(i,s,col+1,tem); } else dfs(i,s+st[col],col+1,tem); } int main() { //freopen("C:\\Users\\ling\\Desktop\\1.in","r",stdin);freopen("C:\\Users\\ling\\Desktop\\2.out","w",stdout); init(); while(scanf("%lld%lld",&width,&height),height+width) { if(height*width%3!=0) { cout<<0<<endl; continue; } memset(dp,0,sizeof(dp)); //dfs(1,0,0,1); dp[0][0]=1; for(int i=1;i<=height;i++) { for(int j=0;j<st[width];j++) { if(dp[(i-1)][j]!=0) { change(j); long long temp = dp[(i-1)][j]; dfs(i,0,0,temp); } } }//DP[I][J]放的是I行,状态J的种数 cout << dp[height][0]<<endl;//应为最后一行的状态就是0 } return 0; }