题目链接
https://www.luogu.com.cn/problem/P1523
思路
我们可以将问题转化成两个人从同一个位置出发,走不同的路,最后到达相同终点的最短路径。
d p [ i ] [ j ] dp[i][j] dp[i][j]表示一个人走到第 i i i个点,另一个人走到第 j j j个点( i > j i > j i>j),且 [ 1 , i ] [1,i] [1,i]的所有点都已经被走过的最短路。
当 i = = j + 1 i == j + 1 i==j+1时,其中一个人可以从第 k k k个点走到第 i i i个点, d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ j ] [ k ] + D i s t a n c e ( p [ k ] , p [ i ] ) ) dp[i][j] = min(dp[i][j], dp[j][k] + Distance(p[k], p[i])) dp[i][j]=min(dp[i][j],dp[j][k]+Distance(p[k],p[i])),其中 k ∈ [ 1 , j ) k \in [1,j) k∈[1,j)。
当 i > j + 1 i > j+1 i>j+1时,第一个人走的上一个点只能是第 i i i个点,所以: d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ i − 1 ] [ j ] + D i s t a n c e ( p [ i − 1 ] , p [ i ] ) ) dp[i][j] = min(dp[i][j], dp[i - 1][j] + Distance(p[i - 1], p[i])) dp[i][j]=min(dp[i][j],dp[i−1][j]+Distance(p[i−1],p[i]))。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef long long i64;
typedef unsigned long long u64;
typedef pair<int, int> pii;
const int N = 1e3 + 5, M = 2e2 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
std::mt19937 rnd(time(0));
int n;
double dp[N][N];
struct Point
{
int x, y;
Point() {}
Point(int x, int y): x(x), y(y) {}
bool operator<(const Point&other) {
if (x != other.x)
return x < other.x;
return y < other.y;
}
} p[N];
double Distance(Point A, Point B)
{
return sqrtl((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
void solve(int test_case)
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> p[i].x >> p[i].y;
}
sort(p + 1, p + 1 + n);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
dp[i][j] = inf;
}
}
dp[2][1] = Distance(p[2], p[1]);
for (int i = 3; i <= n; i++)
{
for (int j = i - 1; j >= 1; j--)
{
if (i == j + 1)
{
for (int k = j - 1; k >= 1; k--)
{
dp[i][j] = min(dp[i][j], dp[j][k] + Distance(p[k], p[i]));
}
}
else
{
dp[i][j] = min(dp[i][j], dp[i - 1][j] + Distance(p[i - 1], p[i]));
}
}
}
double ans = inf;
for (int i = 1; i < n; i++)
{
ans = min(ans, dp[n][i] + Distance(p[i], p[n]));
}
cout << fixed << setprecision(2) << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve(i);
}
return 0;
}