题目描述
Orz likes to play dominoes. Now giving an n*m chessboard and k dominoes whose size are 1 * 2, Orz finds that there is exactly one grid empty, so that he can move dominoes without overlapping them. An initial situation is given, he wants to know how many final situation could be achieved, except the initial situation. Note every domino is different, as they have their own serial number. Since the answer may be very large, please output the answer modulo 1000000009.
输入
There will be multiple test cases. For each test case:
The first line contains three integers: n, m, k(n ≤ 9, m ≤ 10000).
The following k lines, each line contains four integers: a b c d, indicating that this domino occupies (a, b) and (c, d).
The input guarantees that the domino does not overlap, and there is exactly one empty grid.
输出
For each test cases, output the answer modulo 1000000009.
样例输入
5 5 12
1 1 2 1
1 2 2 2
1 3 2 3
1 4 1 5
2 4 2 5
3 4 3 5
3 1 3 2
4 1 4 2
5 1 5 2
4 3 5 3
4 4 5 4
4 5 5 5
样例输出
8
题意:有一种1*2的多米诺骨牌,将k个骨牌其放到一个n * m的棋盘中,有横着放的有竖着放的。最终会塞满整个棋盘,剩余一个空格,这个空格供周围的多米诺牌移动【类似华容道】,问这样移动可以形成多少种不同的空间。输入棋盘大小n和m,输入骨牌个数k,输入每个骨牌占领的格子坐标。
思路,首先我们可以知道,这些牌无论怎样移动,形成的状态都是独一无二的,不会有挪动一圈后又回到之前经历过的某一种状态。因此,我们只需要记录空格出现的位置即可。也就是说,一个空格只能有一种状态,不会有出现同一个位置的空格有两种不同的摆放状态。也不会有相同状态,不同排列的情况。而整个棋盘最大也就是9 * 1e4的大小,空格个数也就是这么多,没错题目中的模1e9+9是个骗人的幌子,根本不会有那么大的数据。
因此我们对于一个空格可以出现的位置,广搜模拟移动计数即可。
可以发现,当占领两个格子的坐标,x相同时是横放,y相同时竖放。用1和2两种状态标注多米诺的摆放。并且,注意我们广搜的过程,因为一个骨牌只能在两个位置移动,不会跑出3个格子,那么我们不用动态的对棋盘的所有骨牌位置状态做模拟,从头到尾广搜利用的棋盘上骨牌位置都是初始骨牌的位置。
还应注意的一点是我们得记录空格是由上下左右哪个骨牌的移动得来的,那么这个方向在新的空格位置就不会忘这个方向来回移动。形成死循环。还应记录空格出现的位置,做vis标记防止再次回到这个位置。我们只需记录不同位置出现的空格次数。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=1e4+9;
struct node
{
int x,y,dir;
node(){}
node(int a,int b,int c)
{
x=a;
y=b;
dir=c;
}
};
int walkx[]={1,0,-1,0};
int walky[]={0,-1,0,1};
int n,m,k;
bool vis[11][maxn];
short int mp[11][maxn];
queue<node>q;
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
int x1,y1,x2,y2;
while(!q.empty())q.pop();
memset(mp,0,sizeof(mp));
memset(vis,false,sizeof vis);
for(int i=0;i<k;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1==x2)mp[x1][y1]=mp[x2][y2]=1;
else mp[x1][y1]=mp[x2][y2]=2;
}
// for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)
// printf("%d%c",mp[i][j],j==m?'
':' ');
bool flag=false;
node st;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]==0)
{
flag=true;
st.x=i;
st.y=j;
st.dir=-4;
break;
}
}
if(flag)break;
}
int ans=-1;
q.push(st);
while(!q.empty())
{
node tmp=q.front();
q.pop();
ans++;
vis[tmp.x][tmp.y]=true;
for(int i=0;i<4;i++)
{
int nx=tmp.x+walkx[i];
int ny=tmp.y+walky[i];
if(nx<=n&&nx>0&&ny<=m&&ny>0&&(tmp.dir+2)%4!=i)
{
if(ny==tmp.y&&mp[nx][ny]==2)
{
if(tmp.x+2*walkx[i]>0&&tmp.x+2*walkx[i]<=n&&!vis[tmp.x+2*walkx[i]][tmp.y])
q.push(node(tmp.x+2*walkx[i],tmp.y,i));
}
if(nx==tmp.x&&mp[nx][ny]==1)
{
if(tmp.y+2*walky[i]>0&&tmp.y+2*walky[i]<=m&&!vis[tmp.x][tmp.y+2*walky[i]])
q.push(node(tmp.x,tmp.y+2*walky[i],i));
}
}
}
}
// printf("=====================
");
// for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)
// printf("%d%c",vis[i][j],j==m?'
':' ');
printf("%d
",ans);
}
}