vijos p1014(旅行商简化版)

动态规划

题目看懂有点困难 其实还是不是很难

一个人从最左到最右最后回到最左点 ,并形成一个环,其实可以看成两个人都从最左点出发,然后以不同的路径到达最右点。

假设一个人达到了第 i 个 点, 第二个人达到了 第J个 点 ,我们可以设i>j ,无论是第一个人还是第二个人走到第i 个点,他们都是等效的。

于是我们就有f[i,j] 来表示 第两个人分别走到 第i个点和第j个点的 最短距离。

假设当前状态是f[i,j],当i-j>1时,由于i 与 j 中间还有(i-j-1)个点,所以该状态只能由 f[i-1,j]得出,所以有 f[i,j]=f[i-1,j]+dist[i,i-1]. 其中 dist[a,b]是 a到b的距离。

当 i-j=1时,就不一样了,此时f[i,j]=min(f[i,j],f[j,k]+dist[k,i]),其中1<k<j-1.

由于我们只能得出f[n,n-1];

所以ans:=f[n,n-1]+dist[n,n-1]。

 1 program p1014;
 2 type
 3         rec=record
 4                 x,y:real;
 5         end;
 6         arr=array[1..1010]of rec;
 7 var
 8         f:array[0..1010,0..1010]of real;
 9         s:arr;
10         i,j,k,l,m,n:longint;
11 function min(a,b:real):real;
12 begin
13         if a>b then min:=b
14         else min:=a;
15 end;
16 {=================================================}
17 function max(a,b:real):real;
18 begin
19         if a>b then exit(a)
20         else exit(b);
21 end;
22 function dist(a,b:longint):real;
23 begin
24         dist:=sqrt(sqr(s[a].x-s[b].x)+sqr(s[a].y-s[b].y));
25 end;
26 {=================================================}
27 procedure pai(w,t:longint);
28 var
29         i,j:longint;
30         k:real;
31 begin
32         i:=w; j:=t;
33         repeat
34         while(i<j)and(s[j].x>=s[i].x) do dec(j);
35         k:=s[j].x; s[j].x:=s[i].x; s[i].x:=k;
36         k:=s[j].y; s[j].y:=s[i].y; s[i].y:=k;
37         while(i<j)and(s[j].x>=s[i].x) do inc(i);
38         k:=s[j].x; s[j].x:=s[i].x; s[i].x:=k;
39         k:=s[j].y; s[j].y:=s[i].y; s[i].y:=k;
40         until i=j;
41         if i>w then pai(w,i-1);
42         if i<t then pai(i+1,t);
43 end;
44 {=================================================}
45 begin
46         read(n);
47         for i:=1 to n do
48                 with s[i] do
49                 begin
50                 read(x,y);
51                 end;
52         pai(1,n);
53         for i:=2 to n do
54                 begin
55                 f[i,1]:=f[i-1,1]+dist(i,i-1);
56                 for j:=2 to i-1 do
57                         begin
58                         if i-j>1 then
59                         begin
60                         f[i,j]:=f[i-1,j]+dist(i,i-1);
61                         f[j,i]:=f[i,j]
62                         end
63                         else
64                         begin
65                         if i-j=1 then
66                         begin
67                         f[i,j]:=1e24;
68                         for k:=1 to j-1 do
69                         f[i,j]:=min(f[i,j],f[j,k]+dist(k,i));
70                         //f[j,i]:=f[i,j];
71                         //f[i,j]:=min(f[i,j],f[i-1,j]+dist(i,i-1));
72                         end
73                         end
74                         end;
75                 end;
76         writeln(f[n,n-1]+dist(n,n-1):0:2);
77 end.             
posted @ 2012-11-17 16:10  改名字干什么  阅读(248)  评论(0编辑  收藏  举报