| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 10402 | Accepted: 6035 |
Description

Input
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
Source
[Submit] [Go Back] [Status] [Discuss]
给一个长,一个宽,求用1*2的地砖能恰好完全覆盖的方法有多少种。
研究了好久,终于有点理解了,采用状态压缩dp来枚举每一层的状态,然后层层递推,最后就可以得到了答案。
dfs状态压缩代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
long long dp[12][(1<<11)+1];
int m,n,k;
void dfs(int c,int s1,int s2)
{
if(c==n)
{
dp[k][s1] += dp[k-1][s2];
return;
}
if(c+1<=n)
{
dfs(c+1,s1<<1,s2<<1|1);
dfs(c+1,s1<<1|1,s2<<1);
}
if(c+2<=n)
dfs(c+2,s1<<2|3,s2<<2|3);
}
int main()
{
while(~scanf("%d%d", &m ,&n) && m)
{
if(n>m) swap(n,m);
memset(dp,0,sizeof(dp));
dp[0][(1<<n)-1]=1;
for(k=1; k<=m; k++)
dfs(0,0,0);
printf("%lld\n",dp[m][(1<<n)-1]);
}
return 0;
}代码:
#include<iostream>
#include<cstring>
using namespace std;
long long f[2][1<<12],i,j,ps,p=0,c=1,n,m;
int main()
{
while (scanf("%d%d",&n,&m),n!=0)
{
memset(f[c],0,sizeof(f[c]));
f[c][(1<<m)-1]=1;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
{
swap(p,c);memset(f[c],0,sizeof(f[c]));
for (ps=0;ps<1<<m;ps++)
if (f[p][ps])
{
if (j>0&&(!(ps&(1<<j-1)))&&(ps&(1<<j))) f[c][ps|1<<(j-1)]+=f[p][ps];
if (!(ps&1<<j)) f[c][ps|1<<j]+=f[p][ps];
if (ps&1<<j) f[c][ps^1<<j]+=f[p][ps];
}
}
printf("%lld\n",f[c][(1<<m)-1]);
}
}
原文:http://blog.csdn.net/xianxingwuguan1/article/details/19039259