UVa 1347 Tour (dp)
阿新 • • 發佈:2021-07-22
題目連結:
一個人走過去走回來不好考慮,可以看成兩個人同時從起點出發,\(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; }