描述:一个棋盘内,有些地方有洞,有些地方没有,没有洞的地方可以放东西,求是否可以用1*2的长方形填满所有格子(除了洞)。当然长方形不能相互覆盖。
很明显是二分图的最大匹配:关键是如何建模,也就是怎么样建立二分图。我的方法是根据格子位置的奇偶性构图;相邻的格子不能在二部图的同一边。然后进行最大匹配就好了。
下面附程序:
const maxn=32; dx:array[1..4] of longint=(1,0,-1,0); dy:array[1..4] of longint=(0,1,0,-1); var n,m,k,x,y,i,w1,b1,j,ans:longint; v1:array[1..maxn,1..maxn] of boolean; v:array[1..maxn*maxn] of boolean; b,w:array[1..maxn*maxn,1..2] of longint; num:array[1..maxn,1..maxn] of longint; link:array[1..maxn*maxn] of longint; function find(x:longint):boolean; var i,p,q,s,r:longint; begin find:=false; for i:=1 to 4 do begin p:=w[x,1]+dx[i]; q:=w[x,2]+dy[i]; if (p<1)or(p>n)or(q<1)or(q>m) then continue; if v1[p,q]=false then continue; s:=num[p,q]; if v[s] then begin v[s]:=false; r:=link[s]; link[s]:=x; if (r=0)or(find(r)) then exit(true); link[s]:=r; end; end; end; begin readln(n,m,k); fillchar(v1,sizeof(v1),true); for i:=1 to k do begin readln(x,y); v1[y,x]:=false; end; for i:=1 to n do for j:=1 to m do begin if v1[i,j]=false then continue; if (i mod 2=1)and(j mod 2=1)or(i mod 2=0)and(j mod 2=0) then begin inc(w1); w[w1,1]:=i; w[w1,2]:=j; num[i,j]:=w1; end else begin inc(b1); b[b1,1]:=i; b[b1,2]:=j; num[i,j]:=b1; end; end; for i:=1 to w1 do begin fillchar(v,sizeof(v),true); if find(i) then inc(ans); end; if ans*2=n*m-k then writeln('YES') else writeln('NO'); end.