zoukankan      html  css  js  c++  java
  • UVA 1347_Tour

    题意:

    给定一系列按x坐标升序排列的点,一个人从左向右走到终点再从终点走回起点,要求每个点恰好经过一次,问所走过的最短路径长度。

    分析:

    可以看成是两个人同时从起点向终点走,且除起点终点外每个点恰有一个人经过。

    John uses the following strategy: he starts from the leftmost point, then he goes strictly left to right to the rightmost point, and then he goes strictly right back to the starting point.

    用d[i][j]表示一个人走到第i个位置,另一个人走到第j个位置时,已经共走了多少距离,规定其中i>j,且1~i全部走过。
    题目要求严格按照从左到右和从右到左的顺序,所以不管哪个人下一步只能走i+1,i+2….如果一个人跳过i+1直接走到了i+2,则i+1必将由另一个人走,不妨让走i+1的人先走,这样便保证每次都先走到i+1,得到状态转移方程:(dist数组保存两点之间距离)

    dp[i+1][j]=min(dp[i+1][j],dp[i][j]+dist[i+1][i]);
    dp[i+1][i]=min(dp[i+1][i],dp[i][j]+dist[i+1][j]);

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=55, INF = 0x3fffffff; //为什么是55?
    double x[maxn],y[maxn],dist[maxn][maxn],dp[maxn][maxn];
    int main(void)
    {
        int n;
        while(scanf("%d",&n) == 1){
            for(int i =0; i < n ; i++)
                scanf("%lf%lf",&x[i], &y[i]);
            for(int i = 0;i < n; i++)
                for(int j = 0 ; j < n ; j++)
                  dist[i][j] = sqrt((x[i] - x[j]) * (x[i]-x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
    
            for(int i = 0; i < n; i++){
                for(int j = 0; j < n; j++)
                    dp[i][j] = INF;
            }
            dp[1][0]=dist[1][0];
    
            for(int i = 1; i < n - 1; i++) {
                for(int j = 0; j < i; j++){
                    dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + dist[i + 1][i]);
                    dp[i + 1][i] = min(dp[i + 1][i], dp[i][j] + dist[i + 1][j]);
                }
            }
    
           double ans = INF;
            for(int i = 0; i < n - 1; i++){
                ans = min(ans, dp[n-1][i] + dist[n - 1][i]);
    
            }
            printf("%.2lf
    ", ans);
        }
        return 0;
    }
    

    还可以用d[i][j]表示一个人走到第i个位置,另一个人走到第j个位置时,还剩多少距离,则状态转移方程

    dp[i][j]=min(dist[i][i+1]+dp[i+1][j],dist[j][i+1]+dp[i+1][i]);  

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=55, INF = 0x3fffffff; //为什么是55?
    double x[maxn],y[maxn],dist[maxn][maxn],dp[maxn][maxn];
    int main(void)
    {
        int n;
        while(scanf("%d",&n) == 1){
            for(int i =0; i < n ; i++)
                scanf("%lf%lf",&x[i],&y[i]);
            for(int i = 0;i < n; i++)
                for(int j = 0 ; j < n ; j++)
                  dist[i][j] = sqrt((x[i] - x[j]) * (x[i]-x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
    
            for(int i = n - 2; i >=1; i--) {
                for(int j = i - 1; j >= 0; j--){
                    if(i == n - 2) dp[i][j] = dist[i][n - 1] + dist[j][n - 1];
                    else
                        dp[i][j] = min(dist[i][i + 1]+dp[i + 1][j], dist[j][i + 1] + dp[i + 1][i]);
             }
        }
            printf("%.2lf
    ", dist[0][1] + dp[1][0]);
        }
        return 0;
    }
    

    貌似叫双调旅行商问题?

  • 相关阅读:
    Unity中传入任意数,转换成分,秒,并进行倒计时换算..(两种方式)
    Unity中调用手机中的粘贴功能
    关于Unity中IphoneX的适配
    可以接受多个字符串的可变参数
    可变参数函数示例
    多维数组指针指向引用问题
    printf的封装与实现
    关于MQTT的相关工具和使用(参考百度天工)
    单片机的堆和栈(Heap & Stack)详解
    单片机的内存分配(变量的存储位置)详解
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758847.html
Copyright © 2011-2022 走看看