Uva 1347 旅行
2017-09-18 21:06
225 查看
Description
给定平面上n个点,设计一条路线,从1号点出发,走到n号点在走回来,除了最左边的点,其他每个点恰好经过一次,且是的路径总长最短。两点之间的路径长度为欧几里得距离(就是直线距离)。Solution
处理从1号点走到n号点在走回来的情况很复杂,所以我们可以假设有2个人一起走,并且走的点不重复。设f[i][j]表示第一个人走到i,第二个人走到j的最优答案。但是这样还是不知道自己走的对方是否走过。
所以设f[i][j]表示1..i都走过,第一个人走到i,第二个人走到j的最优答案。
那么可能是第一个人走到i+1或是第二个人走到i+1。
所以转移变成了f[i][j]→f[i+1][j],f[i][j]→f[i][i+1]。
但这样还是有弊端。
N2的空间很大,必须开滚动数组。假设i和j相差很大,不可能完成所有的转移。
所以强制i>j。
所以f[i][j]→f[i+1][i]和f[i+1][j]。
为什么这样是对的?
在进行点i+1的更新时,我们可以假想是哪个人选了第i+1个点。这个记录过程类似于背包。那么f[i][j]和f[j][i]维护的是一样的东西。
所以可以强制i>j.
Code
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define N 5010 #define DB double #define fo(i,a,b) for(i=a;i<=b;i++) #define fd(i,a,b) for(i=a;i>=b;i--) using namespace std; DB f[2] ; int i,j,k,l,n,o; DB x ,y ; DB dis(int a,int b){ return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])); } int main(){ scanf("%d",&n); fo(i,1,n) scanf("%lf%lf",&x[i],&y[i]); fo(j,1,n-1) f[o][j]=dis(n,n-1)+dis(n,j); fd(i,n-2,2){ o=1-o; fo(j,1,i-1) f[o][j]=min(f[1-o][j]+dis(i+1,i),f[1-o][i]+dis(i+1,j)); } printf("%.4lf",f[o][1]+dis(1,2)); return 0; }
相关文章推荐
- Uva 1347,旅行
- 记忆化搜索,动态规划(旅行,uva 1347)
- 例题9-3 旅行 UVa1347
- UVa 1347 旅行
- 旅行(uva 1347)
- 例题9-3 UVA - 1347 Tour 旅行(DP)
- uva 1347 Tour 旅行
- UVa 1347 例题9-3 旅行 (双调欧几里得旅行商问题)
- UVa 1347 (双线程DP) Tour
- UVA 1347 Tour(双调欧几里得旅行商问题)
- Tour UVA - 1347
- UVA 1347(POJ 2677) Tour(双调欧几里得旅行商问题)
- uva1347 Tour
- UVA 1347 Tour
- 【UVa 1347】Tour
- 平面n个点 求从最左边点到最右边点再返回的最短路长 uva 1347
- UVa1347 Tour
- UVA11100旅行(大包装小包,问最少多少个包)
- Tour UVa 1347
- UVA-1347 Tour