这居然是IOI 98的题目耶,我居然写出来了,想想就有点小激动呢(我绝对不会说出来我看了题解)!
题目大意就是在一个n*m的矩阵中有一个国王和若干个骑士。国王每一步可以往任意方向走一格(包括斜着),骑士每一步走的是日子型(跟象棋里的马一样,没下过的自己面壁去)。当骑士和国王相遇时骑士可以带着国王走,每次只算一步。现在要求所有骑士和国王在任意一点会和最少需要走的步数。
题解:先用bfs求出每个点之间的距离dis[i,j,k,l]然后就开始枚举接国王。s[i,j,1]表示所有骑士走到点(i,j)的最短路径,s[i,j,2]表示某个骑士接王后到点(i,j)的最短路径,然后就开始三重循环。考虑到骑士比王走得快,所以应让王尽量少走,但不排除有些骑士不能到王那里(要是换成我果断把那骑士炒了),所以要枚举王往方圆两格中走。然后计算最小值就好了。但还要考虑到王自己走到集合点的情况。
大概就这样了……最慢的点0.43ms,还是蛮快的。
本人语文成绩比较捉急,大家凑合着看吧(感觉自己都不太看得懂)。
下面附代码(本人是P狗,请勿嘲笑)
const dx:array[1..8] of longint=(1,1,2,2,-1,-1,-2,-2); dy:array[1..8] of longint=(2,-2,1,-1,2,-2,1,-1); var n,m,y,kingx,kingy,a1,i,j,k,w,ans:longint; x:char; a:array[1..780,1..2] of longint; dis:array[1..30,1..26,1..30,1..26] of longint; v:array[1..30,1..26] of boolean; state:array[1..10000,1..3] of longint; s:array[1..30,1..26,1..2] of longint; procedure bfs(x,y:longint); var head,tail,i,p,q:longint; begin fillchar(v,sizeof(v),true); v[x,y]:=false; dis[x,y,x,y]:=0; head:=0; tail:=1; state[1,1]:=x; state[1,2]:=y; state[1,3]:=0; repeat inc(head); for i:=1 to 8 do begin p:=state[head,1]+dx[i]; q:=state[head,2]+dy[i]; if (p<1)or(p>n)or(q<1)or(q>m) then continue; if not v[p,q] then continue; v[p,q]:=false; dis[x,y,p,q]:=state[head,3]+1; inc(tail); state[tail,1]:=p; state[tail,2]:=q; state[tail,3]:=state[head,3]+1; end; until head>=tail; end; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; function work(z,x,y:longint):longint; var s,i,j:longint; begin work:=maxlongint; for i:=max(kingx-2,1) to min(kingx+2,n) do for j:=max(kingy-2,1) to min(kingy+2,m) do begin s:=dis[a[z,1],a[z,2],i,j]+dis[i,j,x,y]+1; if (i=kingx)and(j=kingy) then dec(s); if (i=kingx-2)or(i=kingx+2)or(j=kingy-2)or(j=kingy+2) then inc(s); if s<work then work:=s; end; end; begin readln(n,m); readln(x,y); kingx:=y; kingy:=ord(x)-ord('A')+1; while not eof do begin read(x,y); inc(a1); a[a1,1]:=y; a[a1,2]:=ord(x)-ord('A')+1; if eoln then readln else read(x); end; {for i:=1 to 4 do begin readln(x,y); inc(a1); a[a1,1]:=y; a[a1,2]:=ord(x)-ord('A')+1; end;} fillchar(dis,sizeof(dis),$7f div 3); for i:=1 to n do for j:=1 to m do bfs(i,j); for i:=1 to n do for j:=1 to m do begin for k:=1 to a1 do s[i,j,1]:=s[i,j,1]+dis[a[k,1],a[k,2],i,j]; s[i,j,2]:=maxlongint; end; ans:=maxlongint; for i:=1 to n do for j:=1 to m do begin for k:=1 to a1 do begin w:=work(k,i,j); if s[i,j,1]-dis[a[k,1],a[k,2],i,j]+w<s[i,j,2] then s[i,j,2]:=s[i,j,1]-dis[a[k,1],a[k,2],i,j]+w; end; if s[i,j,1]+dis[kingx,kingy,i,j]<ans then ans:=s[i,j,1]+dis[kingx,kingy,i,j]; if s[i,j,2]<ans then ans:=s[i,j,2]; end; if a1=0 then ans:=0; writeln(ans); end.