P1523 旅行商簡化版(有方向的dp)

題目連接: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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章