SSL P1344 Knights

题目大意:

给出一个N*N的棋盘,在上面有M个位置不能放马,
马的行走方式如下图:
SSL P1344 Knights_第1张图片

求互相不攻击的马最多能放多少个。

n≤200

题解:

匈牙利算法:
这题我们分析发现要求的就是最大独立集,因为有证明得出,最大独立集合=|V|-最大匹配数
而题目很明显最多只能放20000个马,所以我们可以去做二分图匹配,当时20000*20000的数组很明显并不能实现,所以我们发现每个马的攻击点是可求的,所以我们在匹配过程中去寻找连边即可

代码:

const
     dx:array [1..8] of longint=(1,1,-1,-1,2,2,-2,-2);
     dy:array [1..8] of longint=(-2,2,-2,2,-1,1,-1,1);

var
     v:array [0..201,0..201] of boolean;
     p:array [0..201,0..201] of longint;
     xq:array [0..20001,1..2] of longint;
     link:array [0..20001] of longint;
     cover:array [0..20001] of boolean;
     ans,see,you,i,j,n,m,x,y:longint;


function check(aa,bb:longint):boolean;
begin
     if (aa<1) or (aa>n) or (bb<1) or (bb>n) then exit(false);
     if (v[aa,bb]) or (cover[p[aa,bb]]) then exit(false);
     exit(true);
end;

function find(x:longint):boolean;
var
     q,i,x1,y1,k:longint;
begin
     for i:=1 to 8 do
       begin
            x1:=xq[x,1]+dx[i];
            y1:=xq[x,2]+dy[i];
            if check(x1,y1) then
               begin
                     k:=p[x1,y1];
                     q:=link[k];
                     link[k]:=x;
                     cover[k]:=true;
                     if (q=0) or (find(q)) then exit(true);
                     link[k]:=q;
               end;
       end;
     exit(false);
end;

begin
     readln(n,m);
     for i:=1 to m do
       begin
            readln(x,y);
            v[x,y]:=true;
       end;
     for i:=1 to n do
       for j:=1 to n do
         if not(v[i,j]) then
            begin
                 if (i+j) mod 2<>0
                   then begin
                             inc(see);
                             p[i,j]:=see;
                        end
                   else begin
                             inc(you);
                             p[i,j]:=you;
                             xq[you,1]:=i;
                             xq[you,2]:=j;
                        end;
            end;
     ans:=n*n-m;
     for i:=1 to you do
       begin
           fillchar(cover,sizeof(cover),false);
           if find(i) then dec(ans);
       end;
     writeln(ans);
end.

你可能感兴趣的:(pascal,匈牙利算法,匹配)