棋盘覆盖(二)
时间限制:1000 ms | 内存限制:65535 KB
难度:4
- 描述
- The banquet hall of Computer Scientists' Palace has a rectangular form of the size M x N (1<=M<=9, 1<=N<=9). It is necessary to lay hardwood floors in the hall. There are wood pieces of two forms:
1) rectangles (2x1)
2) corners (squares 2x2 without one 1x1 square)
You have to determine X - the number of ways to cover the banquet hall.
Remarks. The number of pieces is large enough. It is not allowed to leave empty places, or to cover any part of a surface twice, or to saw pieces.
- 输入
- The first line contains natural number M. The second line contains a natural number N.
- First line should contain the number X, or 0 if there are no solutions. 样例输入
2 3
样例输出5
铺地砖问题的变形,比原来多了个L型砖,依然用轮廓线去解决(没学过轮廓线的不建议看此博客,白书P383)
观察L砖,发现一共四种形式
(丑,轻喷)
对于第四种来说需要比原本的铺地砖问题的轮廓线还多一个位置,因此对于这题,轮廓线的长度为(m+1)
然后就按照轮廓线的步骤一步步地来
设轮廓线从末尾到开头的第i个位置为P[i]
对于要放的这点一共有7种放法
1:竖着放1*2的地砖,此时需要 P[m]=P[m-1]=1,P[0]=0;
2.横着放1*2的地砖,此时需要 P[m]=1,P[m-1]=0
3.什么也不放,此时需要 P[m]=1
4.放第一种L型砖 当前行不能为第一行,当前列不能为第一列且 P[m]=P[0]=0
5.放第二种L型砖 当前行不能为第一行,当前列不能为第一列且 P[m]=1,P[4]=P[0]=0
6.放第三种L型砖 当前行不能为第一行,当前列不能为最后一列且P[m]=1,P[m-1]=P[m-2]=0
7.放第四种L型砖 当前行不能为第一行,当前列不能为第一列且P[m]=P[m-1]=0
然后将新状态加上原本的方案数就行了
#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <cmath>
#include <algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=11;
ll dp[2][1<<N];
int main()
{
int n,m,cur;
while(~scanf("%d%d",&n,&m))
{
if(n<m)swap(n,m);
cur=0;
dp[0][(1<<m+1)-1]=1;
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
cur^=1;
mem(dp[cur],0);
for(int k=0; k<1<<m+1; k++)
{
if(j&&(k&(1<<m))&&!(k&1))//竖着放1*2的
dp[cur][((k^(1<<m))<<1)|3]+=dp[1-cur][k];
if(i&&(k&(1<<m))&&!(k&(1<<m-1)))//横着放1*2的
dp[cur][((k^(1<<m)|(1<<m-1))<<1)|1]+=dp[1-cur][k];
if(k&(1<<m))//不放
dp[cur][(k^(1<<m))<<1]+=dp[1-cur][k];
if(i&&j&&!(k&(1<<m))&&!(k&1))//第一种L型砖
dp[cur][k<<1|3]+=dp[1-cur][k];
if(i&&j&&(k&(1<<m))&&!(k&(1<<m-1))&&!(k&1))//第二种L型砖
dp[cur][(k^(1<<m)|(1<<m-1))<<1|3]+=dp[1-cur][k];
if(i&&(j!=m-1)&&(k&(1<<m))&&!(k&(1<<m-1))&&!(k&(1<<m-2)))//第三种L型砖
dp[cur][(k^(1<<m)|(3<<m-2))<<1|1]+=dp[1-cur][k];
if(i&&j&&!(k&(1<<m))&&!(k&(1<<m-1)))//第四种L型砖
dp[cur][(k<<1)|(1<<m)|1]+=dp[1-cur][k];
}
}
}
printf("%lld\n",dp[cur][(1<<m+1)-1]);
}
return 0;
}