A. Tiling Dominoes
| A. Tiling Dominoes |
Problem
Given a rectangular grid, with dimensions m x n, compute the number of ways of completely tiling it with dominoes. Note that if the rotation of one tiling matches another, they still count as different ones. A domino is a shape formed by the union of two unit squares meeting edge-to-edge. Equivalently, it is a matching in the grid graph formed by placing a vertex at the center of each square of the region and connecting two vertices when they correspond to adjacent squares. An example of a tiling is shown below.
The Input
The input will consist of a set of lines with m n, given the restriction n*m<101.
The Output
For each line of input, output the number of tilings in a separate line.
Sample Input
2 10 4 10 8 8
Sample Output
89 18061 12988816
N*M的棋盘用1*2的骨牌完全覆盖有多少种方法。
第一次做插头DP。插头DP适合在比较窄的棋盘上进行操作。假设行N比较大,列M比较小,这里用一个M位的状态表示当前状态,设第i行j列的格子编号是i*M+j,那么如果上一次的状态是s[i-M],s[i-M+1]...s[i-1],那么这次的状态就是s[i-M+1],s[i-M+2]...s[i],当前状态S的第j位就是s[i-j],s[i]为0代表编号为i的格子还没有被覆盖,1代表覆盖了。对于每个格子,可以横着放,竖着放,或者暂时不放。要注意判断一些不合法的情况的判断。因为每一步的状态只和上一步的状态有关,所以用滚动数组就行,最后答案是dp[cur][2^M-1]。复杂度O(2^M*N*M)。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN=11;
const int MAXM=20010;
int N,M,cur;
LL dp[2][1<<MAXN];
//a是旧状态,b是新状态
void update(int a,int b){
if(b&(1<<M)) dp[cur][b^(1<<M)]+=dp[!cur][a];
}
int main(){
freopen("in.txt","r",stdin);
while(scanf("%d%d",&N,&M)!=EOF){
if(N<M) swap(N,M);
cur=0;
memset(dp,0,sizeof(dp));
dp[0][(1<<M)-1]=1;
for(int i=0;i<N;i++)
for(int j=0;j<M;j++){
cur=!cur;
memset(dp[cur],0,sizeof(dp[cur]));
for(int k=0;k<(1<<M);k++){
update(k,k<<1); //不放
if(i&&!(k&(1<<(M-1)))) update(k,(k<<1)^(1<<M)^1); //竖着放
if(j&&!(k&1)) update(k,(k<<1)^3); //横着放
}
}
printf("%lld\n",dp[cur][(1<<M)-1]);
}
return 0;
}
本文介绍了一种使用动态规划解决矩形网格完全覆盖问题的方法,即利用1×2的骨牌覆盖mxn的网格,并计算所有可能的覆盖方式。通过插头DP的方式,在较窄的棋盘上进行操作,采用滚动数组减少内存消耗。

3146

被折叠的 条评论
为什么被折叠?



