添加C至G一条路径后便是:
(15,15) (20,15) (30,15)
D E F
*-------* *
| _/| _/
| _/ | _/
| _/ | _/
|/ | /
*-------*-------*-------*-------*
A B C G H
(10,10) (15,10) (20,10) (25,10) (30,10)
输入文件包括牧区、它们各自的坐标,还有一个如下的对称邻接矩阵:
A B C D E F G H22.071068
这道题目用普通的floyd会超时,因为你需要对每一个牧区相连之后都floyd一遍,这样子效率很低,其实我们只需要进行一次floyd。
floyd的时候需注意,一个点到一个点的距离就是sqrt(sqr(x1-x2)+sqr(y1-y2)),不管他是斜线还是直线,都可以用这个计算距离。
然后我们还可以用一个f[i,0]表示第i个点所在牧区的直径,然后我们就可以计算出ans的值max{sqrt(sqr(a[i,1]-a[j,1])+sqr(a[i,2]-a[j,2]))+f[0,i]+f[0,j]},但是这个有可能不是最大的,例如下图:
* //第一个区域,设这个点为i
*--*--* //第二个区域,设这个区域中间那个点为j
当i,j连起来的时候,你会得到3这个答案,但是实际上“最短”的直径,依然为4,所以floyd完后的ans还要判断是不是f[0,i]的最大值。
var
f:array[1..10,1..10,1..10,1..10,1..4,1..4] of Boolean;
bz:array[0..11,0..11] of Boolean;
x1,y1,x2,y2,p1,q1,p2,q2,i,j,fx,fy,ans:Longint;
ch:char;
begin
fillchar(bz,sizeof(bz),true);
for i:=1 to 10 do
begin
for j:=1 to 10 do
begin
read(ch);
if ch='C' then
begin
x1:=i;
y1:=j;
end;
if ch='F' then
begin
x2:=i;
y2:=j;
end;
if ch='*' then bz[i,j]:=false;
end;
readln;
end;
fx:=1;
fy:=1;
p1:=x1;
q1:=y1;
p2:=x2;
q2:=y2;
while true do
begin
inc(ans);
x1:=p1; q1:=y1; x2:=p2; y2:=q2;
case fx of
1:if bz[x1-1,y1] and (x1>1) then dec(x1) else inc(fx);
2:if bz[x1,y1+1] and (y1<10) then inc(y1) else inc(fx);
3:if bz[x1+1,y1] and (x1<10) then inc(x1) else inc(fx);
4:if bz[x1,y1-1] and (y1>1) then dec(y1) else inc(fx);
end;
case fy of
1:if bz[x2-1,y2] and (x2>1) then dec(x2) else inc(fy);
2:if bz[x2,y2+1] and (y2<10) then inc(y2) else inc(fy);
3:if bz[x2+1,y2] and (x2<10) then inc(x2) else inc(fy);
4:if bz[x2,y2-1] and (y2>1) then dec(y2) else inc(fy);
end;
if fx<>4 then fx:=fx mod 4;
if fy<>4 then fy:=fy mod 4;
if (x1=x2) and (y1=y2) then
begin
writeln(ans);
exit;
end;
if f[x1,y1,x2,y2,fx,fy]=false then
begin
f[x1,y1,x2,y2,fx,fy]:=true;
p1:=x1; q1:=y1; p2:=x2; q2:=y2;
end
else
begin
writeln(0);
halt;
end;
end;
end.