Processing math: 0%

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及以前的地方全部都被走过(可以理解为ji擦屁股)。当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\n",ans);
57     }
58     
59     return 0;
60 }
View Code
复制代码

 相同问题:OJ 440

posted @   摇啊摇啊  阅读(170)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示