老曹骑士

8 篇文章 0 订阅

老曹骑士

Time Limits: 1000 ms Memory Limits: 65536 KB

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

题目描述

这道题的意思不多说了吧:
给出n只河蟹的坐标,让你踩死它们并回到原点。
其中河蟹大脑皮层的组织运动的神经中枢出了极大的问题致使他们只能被禁锢在一个格子中无法动弹,只能眼睁睁地看着老曹踩死自己。
当老曹沦落(据说是因过度腐败被抓)到棋盘是,他不是在(1,1)上,而是开外挂在一开始选择一个河蟹踩死它,当时已走步数为0,然后再慢慢地以“日”字走法踩其它河蟹最后回到一开始落下的地方,当然,老曹不能跳出棋盘,因为这意味着dying。

解题思路

好像只有我显得那么与众不同:我竟然用了DP

好吧,我设F[i,j,k,x]表示从第i只河蟹出发,已经才死了j只河蟹,最后到达了第k只河蟹,x为死了的河蟹的状态压缩。
设Distance{i,j}表示第i只河蟹到第j只河蟹的距离。

很好理解

Fi,j,k,x=MinFi,j1,l,x xor 2l1+Distancei,j      (2l1 and x>0  ;   l<>i)

其中 Fi,1,i,2i1=0

MinFi,n,j,2n1+Distancei,j 便是答案

const
    fx:array[1..8,1..2]of shortint=((1,2),(1,-2),(-1,2),(-1,-2),(2,1),(2,-1),(-2,1),(-2,-1));

var
    data:array[1..400,1..3]of integer;
    bz:array[1..20,1..20]of boolean;
    loca:array[1..10,1..2]of longint;
    f:array[1..10,1..10,1..10,1..1023]of longint;
    g:array[1..10,1..10]of longint;
    n,k,i,j,l,ans,h,t,o,s:longint;

{求两只河蟹的距离}
function Get_Steps(x1,y1,x2,y2:longint):longint;
    var x,y,xx,yy,s:longint;
begin
    fillchar(bz,sizeof(bz),true);
    data[1,1]:=x1;data[1,2]:=y1;data[1,3]:=0;
    bz[x1,y1]:=false;h:=0;t:=1;
    while h<t do
    begin
        inc(h);
        x:=data[h,1];y:=data[h,2];s:=data[h,3];
        for o:=1 to 8 do
        begin
            xx:=x+fx[o,1];yy:=y+fx[o,2];
            if(xx<1)or(xx>n)then continue;
            if(yy<1)or(yy>n)then continue;
            if(xx=x2)and(yy=y2)then exit(s+1);
            if bz[xx,yy] then
            begin
                bz[xx,yy]:=false;inc(t);
                data[t,1]:=xx;data[t,2]:=yy;data[t,3]:=s+1;
            end;
        end;
    end;
end;

function min(p,q:longint):longint;
    begin if p<q then exit(p) else exit(q);end;

{Main}
begin
    read(n,k);
    for i:=1 to k do read(loca[i,1],loca[i,2]);
    for i:=1 to k-1 do
        for j:=i+1 to k do
            begin g[i,j]:=Get_Steps(loca[i,1],loca[i,2],loca[j,1],loca[j,2]);g[j,i]:=g[i,j];end;{求两两河蟹的距离}
    fillchar(f,sizeof(f),$7f);
    for i:=1 to k do f[i,1,i,1<<(i-1)]:=0;
    for s:=1 to k do
        for i:=2 to k do
            for j:=1 to k do
                for l:=1 to 1<<k-1 do
                    if l and(1<<(j-1))>0 then
                        for o:=1 to k do
                            if o<>j then
                                if l and(1<<(o-1))>0 then f[s,i,j,l]:=min(f[s,i,j,l],f[s,i-1,o,l xor (1<<(j-1))]+g[o,j]);
    ans:=maxlongint;
    for i:=1 to k do
        for j:=1 to k do ans:=min(ans,f[i,k,j,1<<k-1]+g[i,j]);
    writeln(ans);
end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值