UVa 1347 Tour (dp)

题目链接:

一个人走过去走回来不好考虑,可以看成两个人同时从起点出发,\(dp[i][j]\) 表示第一个人在 \(i\), 第二个人在 \(j\) 时,\(1\)\(max(i,j)\) 的点都走过时的最短距离,因为 \(dp[i][j]\)\(dp[j][i]\) 相同,所以规定 \(i\) 始终是大于 \(j\) 的,每个点可以向 \(dp[i+1][j]\)\(dp[i+1][i]\) 转移,边界情况是 \(dp[2][1] = dis(1,2)\),答案是 \(dp[n][n-1]+dis(n-1,n)\)

时间复杂度 \(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 2010; 
const double INF = 1000000007;

int n;

double dp[maxn][maxn];
double x[maxn], y[maxn];

double dis(int i, int j){
	return sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	while(scanf("%d", &n) != EOF){
		for(int i = 1 ; i <= n ; ++i) scanf("%lf%lf", &x[i], &y[i]);	
		for(int i = 1 ; i <= n ; ++i){
			for(int j = 1 ; j <= n ; ++j){
				dp[i][j] = INF;
			}
		}
		dp[2][1] = dis(1, 2);
		for(int i = 2 ; i < n ; ++i){
			for(int j = 1 ; j < i ; ++j){
				dp[i+1][j] = min(dp[i+1][j], dp[i][j] + dis(i, i+1));
				dp[i+1][i] = min(dp[i+1][i], dp[i][j] + dis(j, i+1));
			}
		}
		printf("%.2lf\n", dp[n][n-1] + dis(n-1, n));
	}
	return 0;
}
posted @ 2021-07-21 22:17  Tartarus_li  阅读(23)  评论(0编辑  收藏  举报