UVA-1347 Tour 动态规划 难以确定的状态

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

题意

给出按x坐标排序的几个点。
欲从最左边不回头的走到最右边,然后再返回最左边。
每个点都要被访问,且只能经过一次。
问最小路程是多少。
n<=1000

思路

紫书动规学习中。
首先想到tsp的状压dp(O(n^2*2^n)),发现n超大,这一定不对。
然后就没有什么正经思路了。

首先发现每个x坐标都不同,且又存在两条路,
那么可以把问题转换一下,问两个人从最左走不同节点到达最右的总路程。
设d(i, j)为走过前i个节点,另一个人现在在j节点时的总路程。
那么有转移方程 d(i, j)=min(d(i+1, j)+dist[i][i+!], d(i+1, i)+dist[j][i+1])
边界条件变成d(0, 0)=0; d(n-1, i)=dist[n-1][i]

提交过程

AC

代码

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000+20;
int n, x[maxn], y[maxn];
double data[maxn][maxn], dist[maxn][maxn];
double dp(int i, int j){
    if (i==n-1) return dist[j][n-1];
    if (data[i][j]>0) return data[i][j];
    
    data[i][j]=min(dp(i+1, i)+dist[j][i+1], dp(i+1, j)+dist[i][i+1]);
    return data[i][j];
}

int main(void){
    while (scanf("%d", &n)==1 && n){
        for (int i=0; i<n; i++)
            scanf("%d%d", &x[i], &y[i]);
        for (int i=0; i<n; i++)
            for (int j=i+1; j<n; j++)
                dist[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
        memset(data, -1, sizeof(data));
        printf("%.2f\n", dp(0, 0));
    }

    return 0;
}
Time Memory Length Lang Submitted
769 None None C++ 5.3.0 2018-08-06 05:10:25

猜你喜欢

转载自www.cnblogs.com/tanglizi/p/9438773.html
今日推荐