标签:des style blog http io ar color os sp
给出一个n*m的棋盘,及一个小的矩形1*2,问用这个小的矩形将这个大的棋盘覆盖有多少种方法。
dp[i][j]:有多少种方法,可以使得第i行的状态为j
dp[i][j]=sum{dp[i-1][k],k可以通过合法变化变成状态j}
0:该位置空余
1:该位置被占
有的人问,每个位置不是3种状态吗?即不放矩形,横放一个矩形,竖放一个矩形
当然了,这样定义状态也是可以的,用三进制。
用三进制的话,位运算什么的都要手写比较麻烦……
还是二进制吧,那为何这样定义是可以的呢?
假设在某位置横放是以这个位置为矩形的左端,竖放是以这个位置为矩形的下端
那么,如果i行j列被占了,那么第i+1行j列是不是不能竖放?
如果i行j列没有被占了,那么第i+1行j列是不是只能竖放?
这样考虑,问题就可以由放矩形变成占据一个位置
如果还是不明白的,看看我的代码就明白了,如果还是不明白……
#include<iostream> #include<cstring> using namespace std; long long dp[20][1<<11]; int n,m; void dfs(int s,int row,int line,long long val) { int i,k; k=m-1; dp[row][line]+=val; for(i=s;i<k;i++) if((line>>i&1)==0) if((line>>i+1&1)==0) dfs(i+2,row,line|(1<<i)|(1<<i+1),val); } int main() { int i,j,k; while(cin>>n>>m) { if(n==0&&m==0) break; memset(dp,0,sizeof(dp)); dfs(0,0,0,1); k=1<<m; for(i=1;i<n;i++) for(j=0;j<k;j++) dfs(0,i,k-1^j,dp[i-1][j]); cout<<dp[n-1][k-1]<<endl; } return 0; }
POJ - 2411
Time Limit:3000MS | Memory Limit:65536KB | 64bit IO Format:%I64d & %I64u |
Description
Input
Output
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
Source
标签:des style blog http io ar color os sp
原文地址:http://blog.csdn.net/stl112514/article/details/41874079