2446:Chessboard
- 总时间限制:
- 2000ms 内存限制:
- 65536kB
- 描述
- Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2 to cover the board. However, she thinks it too easy to bob, so she makes some holes on the board (as shown in
the figure below).
We call a grid, which doesn’t contain a hole, a normal grid. Bob has to follow the rules below:
1. Any normal grid should be covered with exactly one card.
2. One card should cover exactly 2 normal adjacent grids.
Some examples are given in the figures below:
A VALID solution.
An invalid solution, because the hole of red color is covered with a card.
An invalid solution, because there exists a grid, which is not covered.
Your task is to help Bob to decide whether or not the chessboard can be covered according to the rules above. 输入 - There are 3 integers in the first line: m, n, k (0 < m, n <= 32, 0 <= K < m * n), the number of rows, column and holes. In the next k lines, there is a pair of integers (x, y) in each line, which represents a hole in the y-th row, the x-th column. 输出
- If the board can be covered, output "YES". Otherwise, output "NO". 样例输入
-
4 3 2 2 1 3 3
样例输出 -
YES
提示
A possible solution for the sample input.-
题意:
玩个游戏:给出一个m行n列的棋盘,里面有m*n个方格,其中有k个格子上有洞,我们称那些没洞的格子叫正常的格子(normal grid),Bob要遵循两个规则去玩:(1)任何一个正常的格子都要被一张卡覆盖,(卡片是1*2规格的)(2)一张卡要正好覆盖两个相邻的正常格子
我们的任务是帮助Bob决定是否棋盘在上述两个规则下能被覆盖。
思路:
因为棋盘上都是两个格子放一张卡片,所以到最后肯定是两个点两个点连着的。由此想到了二分匹配,具体是这样的:
给每个格子编号,从第一行到最后一行编号为1—12 ,然后每个点跟临近的正常点连接,这就建成了二分图
-
代码:
-
#include<stdio.h> #include<string.h> #define N 2050 int dx[5]={1,0,0,-1}; int dy[5]={0,1,-1,0}; int map[N][N],vis[N][N],ID[N][N],mode[N],used[N]; int n,m,k,t=0; int find(int x)//寻找增广路 { int i; for(i=0;i<t;i++) { if(map[x][i]&&!used[i]) { used[i]=1; if(mode[i]==0||find(mode[i])) { mode[i]=x; return 1; } } } return 0; } int main() { while(scanf("%d%d%d",&n,&m,&k)!=EOF) { memset(vis,0,sizeof(vis)); memset(map,0,sizeof(map)); memset(mode,0,sizeof(mode)); int i,j,x,y; while(k--) { scanf("%d%d",&x,&y); if(x&&y) vis[y-1][x-1]=1; } t=0; for(i=0;i<n;i++) for(j=0;j<m;j++) { if(!vis[i][j]) ID[i][j]=t++; } if(t%2!=0) { printf("NO\n"); continue; } for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(!vis[i][j]) { for(k=0;k<4;k++)//四个方向 (可能双向,所以匹配数变成2倍) { int xi=i+dx[k]; int yi=j+dy[k]; if(xi>=0&&xi<n&&yi>=0&&yi<m&&!vis[xi][yi]) map[ID[i][j]][ID[xi][yi]]=1;//建图 } } } } int s=0; for(i=0;i<t;i++) { memset(used,0,sizeof(used)); if(find(i)) { s++;//记录路的数量 } } if(s==t)//是否 是匹配数的二倍 printf("YES\n"); else printf("NO\n"); } return 0; }