zoukankan      html  css  js  c++  java
  • [UVa-1347] Tour

    题意

    给出坐标系中n个点,要求从最左边的点出发,每一步只能往右走,走到最右边那个点。然后再从最右边那个点出发,每一步只能往左走,回到最左边那个点。整个过程中(除了起点),每个点必须经过且仅经过一次。问最短路(欧几里得距离)?

    $n leq 1000$。

    Solution

    问题等价于两个人从起点出发,走到最右边,两人不能经过同一个点,且两个人经过点的并集为所有点。那么一个人的路径确定以后另个人的路径一定确定。(就是去填补还没走的所有点)

    $dp_{i,j}$表示$1..i$已经走完,且另一个人走到了$j$。枚举状态是$O(n^2)$的,可以通过维护路径前缀和$O(1)$转移。

    复杂度$O(n^2)$。

    记忆化搜索

    /*By DennyQi 2019*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1010;
    const int MAXM = 20010;
    const int INF = 0x3f3f3f3f;
    inline int Max(const int a, const int b){ return (a > b) ? a : b; }
    inline int Min(const int a, const int b){ return (a < b) ? a : b; }
    inline int read(){
        int x = 0; int w = 1; register char c = getchar();
        for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
    }
    struct Coordinate{
        double x,y;
    }a[MAXN];
    int n;
    double dp[MAXN][MAXN];
    bool vis[MAXN][MAXN];
    inline bool cmp(const Coordinate& a, const Coordinate& b){
        return a.x < b.x;
    }
    inline double dist(int i, int j){
        double res = 0.0;
        res = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x) + (a[i].y-a[j].y)*(a[i].y-a[j].y));
        return res;
    }
    double DP(int a, int b){
        if(a < b) swap(a,b);
        if(a == n){
            return dist(b,n);
        }
        if(vis[a][b] || vis[b][a]) return dp[a][b];
        vis[a][b] = vis[b][a] = 1;
        dp[a][b] = min(DP(a+1,b)+dist(a,a+1), DP(a,a+1)+dist(b,a+1));
        dp[b][a] = dp[a][b];
        return dp[a][b];
    }
    int main(){
        freopen(".in","r",stdin);
        n = read();
        for(int i = 1; i <= n; ++i){
            scanf("%lf%lf",&a[i].x,&a[i].y);
        }
        sort(a+1,a+n+1,cmp);
        printf("%.2f", DP(1,1));
        return 0;
    } 

    刷表法

    dp[1][1] = 0;
        for(int i = 1; i <= n; ++i){
            for(int j = i; j <= n; ++j){
                if(i==j && i>1 && i<n) continue;
                if(j < n){
                    dp[i][j+1] = min(dp[i][j+1], dp[i][j] + dist(j,j+1));
                    dp[j][j+1] = min(dp[j][j+1], dp[i][j] + dist(i,j+1));
                }
                else{
                    dp[n][n] = dp[i][n] + dist(i,n);
                }
            }
        }

    填表法

    dp[1][1] = 0;
        for(int i = 1; i <= n; ++i){
            for(int j = i; j <= n; ++j){
                if(i==j && i<n) continue;
                dp[i][j] = dp[i][j-1] + dist(j-1,j);
                if(i+1 == j){
                    for(int k = i-1; k >= 1; --k){
                        dp[i][j] = min(dp[i][j], dp[i][k] + dist(k,j));
                    }
                }
                dp[j][i] = dp[i][j];
            }
        }
  • 相关阅读:
    Hibernate 中 简便proxool连接池配置
    卸载oracle删除注册表脚本
    hibernate的@EmbeddedId嵌入式主键详解
    Activiti工作流学习(三)Activiti工作流与spring集成
    Activiti工作流学习(二)流程实例、执行对象、任务
    Activiti工作流学习(一)部署对象和流程定义
    Enum(枚举类型)的基本应用
    Activiti工作流引擎参考资料
    条形码参考资料
    推荐两款PC健康小软件
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/10372790.html
Copyright © 2011-2022 走看看