Analysis
可以根據i和j性質可以看出,i+j爲奇數的上下相鄰的i’和j’一定是偶數,那麼一個1*2的紙片的i+j一定是一個奇數一個偶數。所以建立一個二分圖兩個集合,將i+j爲奇數的點與上下左右相鄰的點連在一起,當然點不是洞。最後就用匈牙利算法求最大匹配數
Code
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define in read()
#define re register
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+(ch^48);
ch=getchar();
}
return f==1?res:-res;
}
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int n,m,K;
int pos[35][35],vis[2000],match[2000];
inline int idx(int x,int y){return (x-1)*m+y;}
int nxt[10000],head[2000],to[10000],ecnt=0;
inline void add(int x,int y){
nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;
}
int ans=0,dfn=0;
inline int find(int u){
for(re int e=head[u];e;e=nxt[e]){
int v=to[e];
if(vis[v]==dfn) continue;
vis[v]=dfn;
if(match[v]==-1||find(match[v])){
match[v]=u;
return 1;
}
}
return 0;
}
void km(){
memset(match,-1,sizeof(match));
for(re int i=1;i<=n;++i)
for(re int j=1;j<=m;++j){
if(pos[i][j]||(i+j)%2==0) continue;
++dfn;
ans+=find(idx(i,j));
}
}
int main()
{
n=in;m=in;K=in;
for(re int i=1;i<=K;++i) {
int y=in,x=in;
pos[x][y]=1;
}
for(re int i=1;i<=n;++i){
for(re int j=1;j<=m;++j){
if(pos[i][j]||(i+j)%2==0) continue;
for(re int k=0;k<4;++k){
int x=i+dx[k];
int y=j+dy[k];
if(x>=1&&y>=1&&x<=n&&y<=m){
if(pos[x][y]) continue;
add(idx(i,j),idx(x,y));
}
}
}
}
km();
if(ans*2+K==n*m) printf("YES");
else printf("NO");
return 0;
}