# 第九届山东省赛H题 Dominoes 【bfs广搜的应用】

## 题目描述

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


#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define M(a,b) memset(a,b,sizeof(a))
const int MAXN = 1e4+5;
const int INF  = 0x3f3f3f3f;
const int MOD  = 1000000009;
int n,m,k;
int x11,x22,y11,y22;
int sx,sy;
int MAP[15][10005];
struct Node
{
int x,y;
};
int vis[15][10005];///标记访问情况
queue<Node>q;
bool check(int x3,int y3)
{
if(x3>=1&&y3>=1&&x3<=n&&y3<=m)
{
return true;
}
return false;
}
int bfs(int x,int y)
{
int ans=0;
Node temp;
temp.x = x;
temp.y = y;
vis[x][y] = 1;
q.push(temp);
while(!q.empty())
{
Node TOP = q.front();
q.pop();
int xx = TOP.x;
int yy = TOP.y;
if(MAP[xx-1][yy]==2&&check(xx-2,yy)&&vis[xx-2][yy]==0)///下方的格子可以上移，空格子坐标更新为(xx-2,yy),并入队列
{
ans++;
vis[xx-2][yy] = 1;///访问情况更新
Node temp2;
temp2.x = xx-2;
temp2.y = yy;
q.push(temp2);
}
if(MAP[xx+1][yy]==2&&check(xx+2,yy)&&vis[xx+2][yy]==0)///上方的格子可以下移，空格子坐标更新为(xx+2,yy),并入队列
{
ans++;
vis[xx+2][yy] = 1;
Node temp2;
temp2.x = xx+2;
temp2.y = yy;
q.push(temp2);
}
if(MAP[xx][yy-1]==1&&check(xx,yy-2)&&vis[xx][yy-2]==0)///左方的格子可以右移，空格子坐标更新为(xx,yy-2),并入队列
{
ans++;
vis[xx][yy-2] = 1;
Node temp2;
temp2.x = xx;
temp2.y = yy-2;
q.push(temp2);
}
if(MAP[xx][yy+1]==1&&check(xx,yy+2)&&vis[xx][yy+2]==0)///右方的格子可以左移，空格子坐标更新为(xx,yy+2),并入队列
{
ans++;
vis[xx][yy+2] = 1;
Node temp2;
temp2.x = xx;
temp2.y = yy+2;
q.push(temp2);
}
}
return ans;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
M(vis,0);
M(MAP,0);
while(!q.empty()) q.pop();
for(int i=0; i<k; i++)
{
scanf("%d %d %d %d",&x11,&y11,&x22,&y22);
if(x11==x22)///x11和x22相等说明该拼图是横着的
{
MAP[x11][y11] = 1;///1带表横着的
MAP[x22][y22] = 1;
}
else
{
MAP[x11][y11] = 2;///2带表竖着的
MAP[x22][y22] = 2;
}
}
int flag = 0;
for(int i=1; i<=n; i++)///确定初始空格子的位置
{
for(int j=1; j<=m; j++)
{
if(MAP[i][j]==0)
{
flag = 1;
sx = i;
sy = j;
break;
}
}
if(flag) break;
}

int ans = bfs(sx,sy);
printf("%d\n",ans%MOD);

}
return 0;
}