• uva-1347


    题目链接:https://vjudge.net/problem/UVA-1347

    题意:有n个点,给出x、y坐标。找出一条路,从最左边的点出发,严格向右走到达最右点再严格向左回到最左点。问最短路径是多少?

    不看题解我是真的不知道这个题可以用dp做,看了题解一脸懵(这都是些什么啊.......)(这个状态定义的太牛啤)

    大体思路:用dp(i,j)表示A走到i,B走到j时的状态还需要走多远到终点,可以证明dp(i,j)==dp(j,i);dp(i,j)表示 已经 达到这个状态后还需要走多远到达终点,与怎么到达这个状态的并没有关系,所以dp(i,j)和dp(j,i)只是两个人角色对换了而已。 但这会出现一个问题,就是dp(i,j)无法知道i、j之间的某些点是否已经走过了,所以我们需要进一步思考,刚刚我们提到,dp(i,j)==dp(j,i),那么我们就可以始终让i>=j(等于只有终点和起点达到)。如果j>i了,只需要交换A、B的角色即可,即将i换为j,j换为i。 有了这个条件之后,我们就可以规定dp(i,j)规定为:A在i,B在j(i>=j)且i之前的所有点都走过了,这样也不会漏解,为什么呢?我们的自然的方法中,之所以i~j之间有点不知道走过了没,就是因为我们允许A连续走了多步,比如A从P1->P5->P6,而B可能从P1->P2。所以P3,P4我们不知道有没有被A或者B走到,因为我们只知道A走到了P6而B走到了P2。但是你明显发现了,在刚刚那个例子中,P3、P4之后必须要被B走到。所以我们改进的dp(i,j)中可以让A和B一格一格走,要么A走,要么B走(其实只是让顺序变化了一下而已)。有了刚刚的论证,我们的状态转移就变成了下面这样:
    dp[i][j] = min(DP(i + 1, j) + dist(i, i + 1), DP(i + 1, i)+dist(j,i+1));即要么A走,要么B走,如果A走的话,那么走到状态dp(i+1,j);如果B走,那么走到状态dp(i,i+1)到要求前面大于后面,所以dp(i,i+1)==dp(i+1,i)即可。注意dist(i,j)表示i-j的距离。

    #include <stdio.h>
    
    #include <string.h>
    
    #include <math.h>
    #include <algorithm>
    using namespace std;
    const int N = 105;
    const double INF = 0x3f3f3f3f3f3f3f3f;
    int n;
    double x[N], y[N], dp[N][N];
    inline double dis (int a, int b) {
    
        return sqrt((x[a]-x[b])*(x[a]-x[b]) + (y[a]-y[b])*(y[a]-y[b]));
    
    }
    void init () {
        for (int i = 1; i <= n; i++)
    
            scanf("%lf%lf", &x[i], &y[i]);
    
        memset(dp, 0, sizeof(dp));
    
        dp[2][1] = dis(1, 2);
    
    }
    double solve () {
    
        for (int i = 3; i <= n; i++) {
    
            dp[i][i-1] = INF;
            for (int j = 1; j < i-1; j++) {
    
                dp[i][i-1] = min(dp[i][i-1], dp[i-1][j] + dis(i, j));
    
                dp[i][j] = dp[i-1][j] + dis(i, i-1);
    
            }
    
        }
        double ans = INF;
    
        for (int i = 1; i < n; i++)
    
            ans = min(ans, dp[n][i] + dis(n, i));
    
        return ans;
    
    }
    int main () {
    
        while (scanf("%d", &n) == 1) {
    
            init ();
    
            printf("%.2lf
    ", solve ());
    
        }
    
        return 0;
    
    

    最后感谢这位博主:https://blog.csdn.net/qq_28236309/article/details/51931816




  • 相关阅读:
    利用条件变量实现生产者消费者模型
    加密算法
    brk mmap malloc使用
    c++中的RTTI机制
    std::array vector 数组联系和区别
    Intent基本使用
    [WPF]DataGrid C#添加右键弹出选择菜单
    c# 通过解析mp3规范命名并上传服务器
    自定义ComboBox,简简单单实现
    自定义窗体,简简单单实现
  • 原文地址:https://www.cnblogs.com/kayiko/p/10957858.html
Copyright © 2020-2023  润新知