题目描述:
找是否能用1*2的板子覆盖掉方格上没有标成黑洞的地方。保证不覆盖板子,能覆
盖所有空格
解题思路:
首先,回溯是肯定能做的吧,但是估计会超时。。。
匈牙利的话:
同最大独立集里用的变种的匈牙利算法 —— 构建的二分图两边点是相同的,这
里的用一块方片覆盖两个格子的条件,等同于是否两点符合配对条件。那么就等同于
找这样的二分图里,是否能为所有的点找到匹配方。
代码:
#include <stdio.h>
#include <stdlib.h>
#define N 1091
int m,n,k,c[N][N], live[N], visit[N], link[N];
int dfs(int v){
int i;
visit[v] = 1;
for(i=1;i<=n*m;i++){
if(live[i]!=0)
if( c[v][i] && !visit[i]){
visit[i] = 1;
if(link[i] == -1 || dfs(link[i])){
link[v] = i;
link[i] = v;
return 1;
}
}
}
return 0;
}
main(){
int f=1, i, x, y;
memset(live,1,sizeof(live));
scanf("%d %d %d", &m, &n, &k); // m rows, n cols
for(i=1;i<=k;i++){
scanf("%d %d",&y, &x);
live[(x-1)*n+y] = 0;
}
if((m*n-k)%2!=0)
f = 0;
if(1 == f){
//初始化c[][]
for(i=1;i<=n*m;i++){
if(live[i] != 0){
if(i%n!=0 && n>1 && live[i+1]!=0)
c[i][i+1] = 1;
if(i%n!=1 && n>1 && live[i-1]!=0)
c[i][i-1] = 1;
if(i-n>0 && live[i-n]!=0)
c[i][i-n] = 1;
if(i+n<=m*n && live[i+n]!=0)
c[i][i+n] = 1;
}
link[i] = -1;
}
f = 1;
for(i=1;i<=m*n;i++){
if(live[i]!=0){
if(link[i]==-1){
memset(visit,0,sizeof(visit));
if(dfs(i)==0){
f = 0;
break;
}
}
}
}
}
if( 1==f )
printf("YES\n");
else
printf("NO\n");
system("pause");
return 0;
}