POJ 2446 Chessboard 最大匹配

描述:一个棋盘内,有些地方有洞,有些地方没有,没有洞的地方可以放东西,求是否可以用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.


你可能感兴趣的:(POJ 2446 Chessboard 最大匹配)