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.