POJ2446Chessboard

Chessboard

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 21308   Accepted: 6683

Description

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.

Input

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.

Output

If the board can be covered, output "YES". Otherwise, output "NO".

Sample Input

4 3 2
2 1
3 3

Sample Output

YES

Hint


A possible solution for the sample input.

 

題目大意就是給你一個n*m的矩形,有些點不能覆蓋,能否用1*2的矩形將大矩形完全覆蓋(除去不能覆蓋的點)。

兩個正方形組成一個矩形,則可以將問題轉換成是否可以將大矩形相鄰的兩個空格一一匹配,除了不能覆蓋的點,圖上所有空格均被包含在二分圖的最大匹配。

做法一是不分兩個點集,建雙向邊,最後匹配是最大匹配兩倍;做法二是i+j爲奇數的點向偶數點建單向邊,跑最大匹配。

注意坑點:x,y是y行x列的空格不能覆蓋,而不是x行y列,我佛了。。。

另外我竟然因爲把存匹配的數組寫成bool型調了一個小時。。。

做法一

#include <cstdio>
#include <cstring>
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
int map[40][40]; 
int line[1600][1600];
bool used[1600],vis[40][40];
int cnt,ans[1600];
bool found(int x)
{
	for(int i=1;i<cnt;i++)
	{
		if(line[x][i]&&!used[i])
		{
			used[i]=1;
			if(!ans[i]||found(ans[i]))
			{
				ans[i]=x;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	int n,m,k;
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		mem(vis,0);
		mem(line,0);
		int x,y;
		for(int i=0;i<k;i++)
		{
			scanf("%d%d",&x,&y);
			vis[y][x]=1;
		}
		if((n*m-k)&1)
		{
			printf("NO\n");
			continue;
		}
		cnt=1;
		for(int i=0;i<=n;i++)
			vis[i][0]=1;
		for(int i=0;i<=m;i++)
			vis[0][i]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(vis[i][j])
					continue;
				map[i][j]=cnt++;
				if(!vis[i-1][j])
					line[map[i-1][j]][map[i][j]]=line[map[i][j]][map[i-1][j]]=1;
				if(!vis[i][j-1])
					line[map[i][j-1]][map[i][j]]=line[map[i][j]][map[i][j-1]]=1;
			}
		}
		mem(ans,0);
		int res=0;
		for(int i=1;i<cnt;i++)
		{
			mem(used,0);
			if(found(i))
				res++;
		}
		if(res+k==n*m)
			printf("YES\n");
		else
			printf("NO\n");
	}
}

做法二:

#include <cstdio>
#include <cstring>
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
int map[50][50]; 
int line[2000][2000];
bool used[2000],vis[50][50];
int cnta,cntb,ans[2000];//竟然把ans定義到bool裏了 
bool found(int x)
{
	for(int i=1;i<cntb;i++)
	{
		if(line[x][i]&&!used[i])
		{
			used[i]=1;
			if(!ans[i]||found(ans[i]))
			{
				ans[i]=x;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	int n,m,k;
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		mem(vis,1);
		mem(line,0);
		int x,y;
		for(int i=0;i<k;i++)
		{
			scanf("%d%d",&x,&y);
			vis[y][x]=0;
		}
		cnta=cntb=1;
		for(int i=0;i<=n+1;i++)//四周都要封 
			vis[i][0]=vis[i][m+1]=0;
		for(int i=0;i<=m+1;i++)
			vis[0][i]=vis[n+1][i]=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(!vis[i][j])
					continue;
				if(((i+j)&1)==1)
					map[i][j]=cnta++;
				else
					map[i][j]=cntb++;
			}
		}
		if(cnta!=cntb)
		{
			printf("NO\n");
			continue;
		}
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				if(((i+j)&1)==0||!vis[i][j])//&的優先級比==低,所以(i+j)&1==0永遠是假!!!!(&,|,^。都比==低) 
					continue;
				if(vis[i-1][j])
					line[map[i][j]][map[i-1][j]]=1;
				if(vis[i][j-1])
					line[map[i][j]][map[i][j-1]]=1;
				if(vis[i+1][j])
					line[map[i][j]][map[i+1][j]]=1;
				if(vis[i][j+1])
					line[map[i][j]][map[i][j+1]]=1;	
			}
		mem(ans,0);
		int res=0;
		for(int i=1;i<cnta;i++)
		{
			mem(used,0);
			if(found(i))
				res++;
		}
		if(res*2+k==n*m)
			printf("YES\n");
		else
			printf("NO\n");
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章