1313. 老曹骑士 TJ

  1. 老曹骑士 (Standard IO)

Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

Description

  我们的主角——老曹陨落于国际象棋棋盘,成为了一位老曹骑士,于是,他开始走“日”字型路线。
  在一张N*N的棋盘上,有K只邪恶的河蟹,骑士曹现在要消灭这些河蟹。
  要求曹从任意一只河蟹出发,通过他“日”字型的跳跃,到达这K个点至少一次,并最终回到起点。
  现在已知棋盘的大小N,和这K只河蟹的位置(棋盘的左上角坐标记为(1,1),右下角坐标记为(N,N)。
  询问:曹最少要跳多少步。

Input

  第一行:两个整数,N,K(4<=N<=20,1<=K<=10)
  接下来K行:每行两个整数X,Y,表示河蟹所在位置。

Output

  一个整数,表示曹所需要条的最少步数。

Sample Input

8 3

2 3

4 5

6 7

Sample Output

12

正解BFS求出每两个河蟹之间的距离,用DFS求最小值。

我的方法:用深搜(记忆化搜索)求出每两个河蟹之间的距离,用全排列求出每种情况下的值,输出最小值即可。
(谢绝co标)code:

uses
        math;
var
    i,j,n,k,l,s,ans:longint;
    hx:array[1..10,1..2]of longint;//河蟹位置
    map,a:array[0..21,0..21]of longint;//棋盘和记忆化数组
    f:array[1..10,1..10]of longint;//记录每两个河蟹之间的距离
    b:array[1..10]of boolean;//全排列标记
    sx:array[0..10]of longint;//跳顺序枚举(全排列)
    fx:array[1..8,1..2]of longint=((1,2),(2,1),(2,-1),(1,-2),(-1,-2),(-2,-1),(-2,1),(-1,2));//老曹可以跳的八个方向
procedure get(x,y:Longint);//求每两个河蟹之间的距离
var
    t1,t2,j:longint;
begin
    if i<>map[x,y] then
    begin
        if map[x,y]>=1 then
        begin
            if f[i,map[x,y]]>a[x,y]then
            begin
                f[i,map[x,y]]:=a[x,y];
                f[map[x,y],i]:=a[x,y];
                exit;
            end;
        end;
    end;
    for j:=1 to 8 do
    begin
        t1:=x+fx[j,1];
        t2:=y+fx[j,2];
        if (t1>=1)and(t1<=n)and(t2>=1)and(t2<=n)then
        if a[t1,t2]>a[x,y]+1 then
        begin
            a[t1,t2]:=a[x,y]+1;
            get(t1,t2);
        end;
    end;
end;
procedure dg(x:longint);//全排列
var
    i:longint;
begin
    if x-1=k then
    begin
        s:=0;
        for i:=1 to k-1 do
        begin
            s:=s+f[sx[i],sx[i+1]];
        end;
        s:=s+f[sx[i+1],sx[1]];
        ans:=min(ans,s);
    end;
    for i:=1 to k do
    begin
        if b[i]=false then
        begin
            inc(sx[0]);
            sx[sx[0]]:=i;
            b[i]:=true;
            dg(x+1);
            dec(sx[0]);
            b[i]:=false;
        end;
    end;
end;
begin
    readln(n,k);
    if k=1 then 
    begin   
        writeln(0);
        exit;
    end;
    for i:=1 to k do
    begin
        readln(l,s);
        hx[i,1]:=l;
        hx[i,2]:=s;
        map[l,s]:=i;
    end;
    fillchar(f,sizeof(f),100);
    for i:=1 to k do
    begin
        fillchar(a,sizeof(a),102);
        a[hx[i,1],hx[i,2]]:=0;
        get(hx[i,1],hx[i,2]);
    end;
    ans:=maxlongint;
    dg(1);
    writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值