算法:DP
分析:可以模拟出两个人走路,设A走到i,B走到j,用f[i,j]表示A走到i,B走到j,且从1到max(i,j)都已走过时的最小经过的城市数。现在我们假设i总是大于j。
根据f[i,j],我们就可以得出两种情况:
1.当B走到i-1时,A的上一步一定不是i-1,一定是2~i-2的某一个城市(为什么不是1呢?因为要满足i总是大于j的假设啊。)
2.当A上一步是i-1时,B的上一步一定不是i-1,一定是1~i-2的某一个城市。
由此我们得到转移方程:
f[i,i-1]=f[j,i-1]+d[j,i]
f[i,j]=f[i-1,j]+d[i-1,i]
分析:可以模拟出两个人走路,设A走到i,B走到j,用f[i,j]表示A走到i,B走到j,且从1到max(i,j)都已走过时的最小经过的城市数。现在我们假设i总是大于j。
根据f[i,j],我们就可以得出两种情况:
1.当B走到i-1时,A的上一步一定不是i-1,一定是2~i-2的某一个城市(为什么不是1呢?因为要满足i总是大于j的假设啊。)
2.当A上一步是i-1时,B的上一步一定不是i-1,一定是1~i-2的某一个城市。
由此我们得到转移方程:
f[i,i-1]=f[j,i-1]+d[j,i]
f[i,j]=f[i-1,j]+d[i-1,i]
最后输出为f[n-1,n]+d[n-1,n](因为f[n,n]的状态没有表示,而f[n-1,n]已经算出,再加上一个定值即可。)
program Vijos1014;
const
maxn=1000;
type
atp=record
x,y:real;
end;
var
n:longint;
a:array [0..maxn] of atp;
d,f:array [0..maxn,0..maxn] of real;
procedure init;
var
i:longint;
begin
readln(n);
for i:=1 to n do readln(a[i].x,a[i].y);
end;
procedure qsort(l,r:longint);
var
i,j:longint;
m:real;
t:atp;
begin
i:=l;
j:=r;
m:=a[(l+r) shr 1].x;
repeat
while a[i].x<m do inc(i);
while a[j].x>m do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
function min(x,y:real):real;
begin
if x<y then exit(x) else exit(y);
end;
procedure ycl;
var
i,j:longint;
t:real;
begin
for i:=1 to n do
begin
for j:=1 to n do
d[i,j]:=sqrt(sqr(a[i].x-a[j].x)+sqr(a[i].y-a[j].y));
end;
end;
procedure main;
var
i,j:longint;
begin
f[1,1]:=0;
for i:=1 to n do
begin
for j:=1 to i-2 do
begin
f[i,j]:=f[i-1,j]+d[i-1,i];
f[j,i]:=f[i,j];
end;
f[i,i-1]:=f[i-1,1]+d[1,i];
f[i-1,i]:=f[i,i-1];
for j:=2 to i-2 do
begin
f[i,i-1]:=min(f[i,i-1],f[j,i-1]+d[j,i]);
f[i-1,i]:=f[i,i-1];
end;
end;
end;
begin
assign(input,'VJ1014.in'); reset(input);
assign(output,'VJ1014.out'); rewrite(output);
init;
qsort(1,n);
ycl;
main;
writeln(f[n-1,n]+d[n-1,n]:0:2);
close(input); close(output);
end.
本文采用动态规划算法解决两人在城市中行走并覆盖所有已访问城市的最短路径问题。通过构建状态转移方程,计算出两人从不同起始点到达终点时的最短路径,最终输出总路径长度。
9138

被折叠的 条评论
为什么被折叠?



