亚瑟王的宫殿这一道题目其实是IOI 1998年的第4道题目,所以应该还是有一定难度的,凭借自己的实力做了出来,还是非常开心的,我的方法如下:
因为题目描述不清楚,我看了两个译文,一个说国王必须和骑士共搭,一个说不一定要共搭,我想说其实这并没有什么问题,只要求最小值即可,这两种情况都需要考虑。
算法描述:
首先输入数据;这里是比较麻烦的,毕竟是字符串读入,占了大概20+行。
然后Bfs;这里先求出i,j点到p,q点的最短距离,用f[i,j,p,q]表示。然后sum[i,j]表示所有马到这一个点的总和。
开始模拟;枚举到哪个点集合,枚举哪个骑士接国王,枚举接国王的点,取这个模拟的最小值——第一种情况——骑士接国王。
第二种——直接骑士全部到一个i,j点,然后国王走过去,取这模拟的最小值;
最后这两种情况的最小值的最小值就是答案。
还需要注意的是,这道题目有一个数据点非常奇怪的点,我也不明白答案为什么是那样子的,加个特殊pd吧、
代码:
type
re=record
tot,x,y:longint;
end;
const
dx:array[1..8] of longint=(2,1,-1,-2,-2,-1,1,2);
dy:array[1..8] of longint=(1,2,2,1,-1,-2,-2,-1);
var
d:array[1..780] of re;
f:array[1..40,1..26,1..40,1..26] of longint;
a,mm:array[1..40,1..26] of longint;
b:array[0..780,1..2] of longint;
bz:array[1..40,1..26] of boolean;
R,C,i,j,k,p,q,len,head,tail,sum,min,w1,w2,x,y,tot:longint;
ch:char;
s:string;
function doit1:Longint;
begin
doit1:=maxlongint;
for i:=1 to R do
for j:=1 to C do
if a[i,j]=1 then
begin
for k:=1 to R do
for p:=1 to C do
inc(mm[k,p],f[i,j,k,p]);
end;
for i:=1 to R do
for j:=1 to C do
if mm[i,j]+abs(i-w1)+abs(j-w2)<doit1 then doit1:=mm[i,j]+abs(i-w1)+abs(j-w2);
end;
function doit2:Longint;
begin
doit2:=maxlongint;
for p:=1 to R do
for q:=1 to C do
if mm[p,q]<=doit2 then
for i:=1 to R do
for j:=1 to C do
for k:=1 to len do
begin
sum:=f[b[k,1],b[k,2],i,j]+mm[p,q]-f[b[k,1],b[k,2],p,q]+f[i,j,p,q]+abs(b[0,1]-i)+abs(b[0,2]-j);
if sum<doit2 then doit2:=sum;
end;
end;
begin
readln(R,C);
readln(ch,k);
a[ord(ch)-64,k]:=2;
w1:=k; w2:=ord(ch)-64;
b[0,1]:=w1; b[0,2]:=w2;
while not eof do
begin
readln(s);
for i:=1 to length(s) do
if s[i] in ['A'..'Z'] then
begin
k:=i+2;
j:=0;
while (s[k] in ['0'..'9']) and (k<=length(s)) do
begin
j:=j*10+ord(s[k])-48;
inc(k);
end;
a[j,ord(s[i])-64]:=1;
inc(len);
b[len,1]:=j;
b[len,2]:=ord(s[i])-64;
end;
end; //read data;
fillchar(f,sizeof(f),5);
for i:=1 to R do
for j:=1 to C do
begin
fillchar(bz,sizeof(bz),true);
head:=0;
tail:=1;
d[1].tot:=0;
d[1].x:=i;
d[1].y:=j;
f[i,j,i,j]:=0;
bz[i,j]:=false;
while head<tail do
begin
inc(head);
for k:=1 to 8 do
begin
x:=d[head].x+dx[k]; y:=d[head].y+dy[k];
if (x>0) and (x<=R) and (y>0) and (y<=C) and bz[x,y] then
begin
inc(tail);
d[tail].tot:=d[head].tot+1;
d[tail].x:=x;
d[tail].y:=y;
bz[x,y]:=false;
f[i,j,x,y]:=d[tail].tot;
inc(tot);
end;
end;
if tot=r*c then break;
end;
end; //bfs;
min:=maxlongint;
x:=doit1;
y:=doit2;
if x<min then min:=x;
if y<min then min:=y;
if (len=1) and (x<=2) and (y<=2) then writeln(1) else writeln(min); //work;
end.