Tour UVa 1347 (DAG)

本题难在设置状态表示。

题目要求先从左到右,再从右到左沿x轴方向经历坐标系上的点(1~n点),可以考虑成两条路径,分别从最左到最右,分别经历不同点且不能重合(除了起点和终点)。可以想到用$d(i,j)$表示一条路走到了$i$,一条路走到了$j$。因为两条路加起来要cover路径上所有点,所以$d(i,j)$可以表示$max(i,j)$和之前的点已经全被走过,还需走多远才能满足条件。因为两条路没有优劣,所以$d(i,j)==d(j,i)$,为了方便操作,可以规定要求$i>j$。可以用例子来理解:第一个人走到2,第二个人就只能停在1了,第一个人走到3,第一个人可以走到1或者2,第一个人走到4,第一个人可以走到1,2,3,始终让$i>j$可以满足结构的清晰。也就是说,$i$决定自己已经走到了最远的地方,而此时$j$停留在哪个地方,来保证$i$及以前的地方全部都被走过(可以理解为$j$给$i$擦屁股)。当$i$到达n时,$j$可以在路上$(1 ~ n-1)$中任何点,因为它走的是$i$走剩的点,所以$d(n,j)=0$。而状态方程可以写为:$d(i,j)=min[d(i+1,j)+dist(i,i+1),d(i+1,i)+dis(j,i+1)]$,其中$dist(a,b)$表示$a,b$之间的距离。

边界条件:当$i$到达n时,$j$可以在路上$(1 ~ n-1)$中任何点,因为它走的是$i$走剩的点,所以$d(n,j)=0$。(这个边界条件是错误的,因为两条路径最终都要到最右端),我们可以理解$d(n,j)=dist(j,n)$,和上面的状态方程结合起来,可以得到$d(n-1,j)=dist(n-1,n)+dist(j,n)$(刘汝佳)(我觉得还是分开来看来处理边界条件比较方便)。起始的时候,因为规定了$i>j$,所以只能写$$d(2,1)$,然后加上1走到2的距离就是总距离了。

代码如下:

 1 //
 2 //  main.cpp
 3 //  Tour
 4 //
 5 //  Created by Yanbin GONG on 12/3/2018.
 6 //  Copyright © 2018 Yanbin GONG. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <stdio.h>
11 #include <string>
12 #include <string.h>
13 #include <algorithm>
14 #include <cmath>
15 
16 using namespace std;
17 
18 struct coord{
19     int x,y;
20 };
21 
22 int n;//number of points
23 coord nodes[105]; //假设最多100个点,UVa官网貌似没给大小
24 double d[105][105];
25 bool visited[105][105];
26 double ans;
27 
28 
29 double dis(int a, int b){
30     return sqrt((nodes[a].x-nodes[b].x)*(nodes[a].x-nodes[b].x)+(nodes[a].y-nodes[b].y)*(nodes[a].y-nodes[b].y));
31 }
32 
33 double dp(int a, int b){
34     if(visited[a][b]==true){
35         return d[a][b];
36     }
37     visited[a][b] = true;
38     if(a==n){
39         d[a][b] = dis(b,n);
40         return d[a][b];//终点条件
41     }
42     d[a][b] = min(dp(a+1,b)+dis(a,a+1),dp(a+1,a)+dis(b,a+1));
43     return d[a][b];
44 }
45 
46 int main(){
47     //原题用freopen,读取文件
48     while(scanf("%d",&n)!=EOF){
49         memset(d,0x3f,sizeof(d));
50         memset(visited,0,sizeof(visited));
51         for(int i=1;i<=n;i++){
52             cin>>nodes[i].x>>nodes[i].y;
53         }
54         dp(2,1);
55         ans = d[2][1] + dis(1,2);
56         printf("%.2lf
",ans);
57     }
58     
59     return 0;
60 }
View Code

 相同问题:OJ 440

原文地址:https://www.cnblogs.com/cmbyn/p/8548651.html