二分图 JT的难题

(problem.cpp/pas)
【问题描述】
亮姐很喜欢下棋,有一天,他看见了无所事事的JT
“哇,你今天竟然有空!”
“今天放假嘛”
“那过来陪我下棋”
JT“······”
亮姐的棋盘很奇葩,是一个N*N的正方形棋盘,上面有一些国际象棋中的马。棋盘的行用1开始的N 个自然数标记,列用’A’开始的N 个大写英文字母标记。若一个马放置在格子(x, y)。那么格子(x-2, y-1), (x-2, y+1), (x-1, y-2),(x-1, y+2), (x+1, y-2), (x+1, y+2), (x+2, y-1), (x+2, y+1)如果在棋盘内的话,就都处于这个马的攻击范围内。如果若干个马在棋盘上的一种放置方法能使得没有一个马处在其它马的攻击范围内,那么称为和谐的方案。现在上面已经有N个棋子。
亮姐:“JT,你说我最少要拿掉多少棋子让剩下的棋子和谐?”
JT:“我怎么知道?”
亮姐:“你不是学编程的吗?”
JT:“······”
唉,没办法,JT实在是弱爆了,现在只能向你求救,告诉他最少拿走的个数。

【输入格式】
第一行,两个正整数N,M,分别表示棋盘的大小,和马的数目。
以下M 行,每行描述一个马的坐标。

【输出格式】
输出一行,一个整数,表示至少拿走多少个马。

【样例输入】
6 9
A1
A5
B3
C5
C1
D2
D4
E6
F5
【样例输出】
3

【Hint】
30%的数据满足,1 <= N <= 4.
100%的数据满足,1 <= N <= 26.

匈牙利算法

program cx;
const dx:array[1..8]of longint=(2,2,1,1,-1,-1,-2,-2);
      dy:array[1..8]of longint=(1,-1,2,-2,2,-2,1,-1);
var i,n,m,x,y,ans,j:longint;
    bx,by,a:array[0..1000]of longint;
    g,gg:array[-2..200,-2..200]of longint;
    v:array[0..1000]of boolean;
    ch:char;

//=================culex===================

function find(x:longint):boolean;
var i:longint;
begin
  for i:=1 to m do
    if (gg[x,i]=1)and not v[i] then
      begin
        v[i]:=true;
        if (a[i]=0) or find(a[i]) then
          begin
            a[i]:=x;
            exit(true);
          end;
      end;
  exit(false);
end;

begin
  assign(input, 'problem.in'); reset(input);
  assign(output,'problem.out');rewrite(output);
  readln(n,m);
  for i:=1 to m do
    begin
      read(ch);
      bx[i]:=ord(ch)-64;
      readln(by[i]);
      g[bx[i],by[i]]:=i;
    end;

  for i:=1 to m do
    begin
      x:=g[bx[i],by[i]];
      for j:=1 to 8 do
        begin
          y:=g[bx[i]+dx[j],by[i]+dy[j]];
          if y>0 then
            begin
              gg[x,y]:=1;
              gg[y,x]:=1;
            end;
        end;
    end;

  for i:=1 to m do
    begin
      fillchar(v,sizeof(v),0);
      if find(i) then inc(ans);
    end;

  writeln(ans>>1);
  close(input);
  close(output);
end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值