• UVA 1347 Tour DP


      题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=446&page=show_problem&problem=4093

      题目描述: 有N个点, 要求求一个回路的最短距离。(N <= 1000)

      解题思路: 一开始想暴力的, 因为实在想不出其他方法了啊....走一圈周长最短可以等价为两个人同时从最左端出发,沿着不同的路径走到最右端。如果定义d(i,j)表示1~max(i,j)全部走过,第一个              人在i,第二个人在j,还需要走多长的距离。此时可以规定i>j,这样,还可以规定i,j中只有一个人允许走到i+1这一点。这样的话可以保证不会出现某些点跳过的情况。状态转移方程如下:

            d(i,j)=min(d(i+1,j)+dist(i,i+1),d(i+1,i)+dist(j,i+1));

            第二项表示为d(i+1,i)是因为已经规定i>j,又根据d(i,j)的定义易知有d(i,j)=d(j,i),因此d(i,i+1)可写为d(i+1,i)。本题的状态数有O(N^2)个,每次状态的决策只有2个,因此时间复杂度为                 O(N^2)。本题中由于j<i,因此还可以提前计算好所有j<i的距离,这样可以避免重复计算距离,进一步提升效率。

      代码:   

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    using namespace std;
    
    struct Node {
        double x;
        double y;
        Node() { x = y = 0; }
        Node( double _x, double _y ) {
            x = _x;
            y = _y;
        }
    };
    Node a[1050];
    double d[1050][1050]; // d(i, j)表示1 ~ max(i, j)都已经走过, 且第一个人到了i, 第二个人到了还需要走多长距离
    int n;
    
    double dis( int i, int j ) {
        double dx = a[i].x - a[j].x;
        double dy = a[i].y - a[j].y;
        return sqrt(dx*dx + dy*dy);
    }
    
    double dp( int i, int j ) {
        double & ans = d[i][j];
        if( ans > 0 ) return ans;
        if( i == n-1 ) return ans = dis(i, n) + dis(n, j);
        return ans = min( dp(i+1, j) + dis(i, i+1), dp(i+1, i) + dis(i+1, j) );
    }
    
    int main() {
        while( ~scanf( "%d", &n ) ) {
            memset(a, 0, sizeof(a));
            memset(d, 0, sizeof(d));
            for( int i = 1; i <= n; i++ ) {
                scanf( "%lf%lf", &a[i].x, &a[i].y );
            }
            printf( "%.2lf
    ", dp(2, 1)+dis(2, 1) );
        }
        return 0;
    }
    View Code

      思考: 这尼玛好难想啊, 这状态真的是好难, 可以看出来我对DP理解还是不够深, 再多做题巩固吧

  • 相关阅读:
    企业应用架构研究系列三:应用系统集成
    企业应用架构研究系列十九:Docker开发环境
    企业应用架构研究系列二十:创建&发布Docker
    前端NEXT实践系列:(一)ECMAScript 6.0技术栈
    企业应用架构研究系列二十七:Vue3.0 之环境的搭建与Vue Antd Admin探索
    企业应用架构研究系列五:极限编程(XP)& 敏捷管理(Scrum)
    记一次HIV初筛假阳性的经历
    C#发送邮件
    Ubuntu允许root登录
    lerna学习
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7270865.html
Copyright © 2020-2023  润新知