題目連接:https://www.luogu.com.cn/problem/P1523
參考文章:https://www.luogu.com.cn/blog/user31197/solution-p1523
思路:
因爲是從東向西,所以先按照x進行排序,假設一個起始點0,這個點和最東邊的點1點2的距離都是0,可以設立狀態dp[i][j]表示一條路徑到i,另一條路徑到j(i<j)的情況下走過的最短路徑和爲dp[i][j]。求出最小的dp[i][n] + dis[i][n]就是最終的最短距離。
更新方式:
dp[i][j+1] = min(dp[i][j+1],dp[i][j] + dis[j][j+1]);
dp[j][j+1] = min(dp[j][j+1],dp[i][j] + dis[i][j+1]);
代碼:
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
const double inf = 1e18+10;
struct Node{
double x,y;
}cur[N];
double dis[N][N] = {0},dp[N][N] = {0};
bool cmp(Node a,Node b)
{
return a.x < b.x;
}
double f(Node a,Node b)
{
return sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) );
}
int main(void)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&cur[i].x,&cur[i].y);
sort(cur+1,cur+1+n,cmp);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
dp[i][j] = inf;
dis[i][j] = f(cur[i],cur[j]);
}
dp[1][2] = dis[1][2];
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<n;j++)
{
dp[i][j+1] = min(dp[i][j+1],dp[i][j] + dis[j][j+1]);//從j跳到j+1
dp[j][j+1] = min(dp[j][j+1],dp[i][j] + dis[i][j+1]);//從i跳到j+1
}
}
double ans = inf;
for(int i=1;i<n;i++)
ans = min(ans,dp[i][n] + dis[i][n]);
printf("%.2f\n",ans);
return 0;
}