- 老曹骑士 (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.