UVA1347-Tour 双调欧几里得旅行商问题 - 递归记忆实现

题意:
平面上有n个坐标均为正数的点,按照x坐标从小到大一次给出。求一条最短路线,从最左边的点出发到最右边的点,再回到最左边的点。除了第一个和最右一个点其他点恰好只经过一次。

分析:
可以等效为两个人从第一个点出发,沿不同的路径走到最右点。
d(i, j)表示点1~max(i, j)这些点全部都走过,而且两人的位置分别是i和j,最少还需要走多长的距离。由这个定义可知,d(i, j) == d(j, i),所以我们再加一个条件,d(i, j)中i>j
这样状态d(i, j)只能转移到d(i+1, j)和d(i+1, i)
边界:d(n-1, j) = dist(n-1, n) + dist(j, n) (1 ≤ j < n-1)
原题链接
OJ地址

#include <stdio.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

#define RPE(I,A,B) for( int I=(A),_END_=(B);I<=_END_;I++)
#define RPED(I,A,B) for( int I=(A),_END_=(B);I>=_END_;I--)

#define RP(I,A,B) for( int I=(A),_END_=(B);I<_END_;I++)
#define RPD(I,A,B) for( int I=(A),_END_=(B);I>_END_;I--)
#define MM(A,V) memset(A,V,sizeof(A))
#define pb(X) push_back(X)

using namespace std;
#define DS(x1,y1,x2,y2) (sqrt(pow((x1)-(x2),2)+pow((y1)-(y2),2)))
#define DIST(i,j) DS(x[(i)],y[(i)],x[(j)],y[(j)])
#define INF 10000

int n;
int x[100];
int y[100];
double d[100][100];

double dp(int i,int j) {
    double& ans=d[i][j];
    if((n-2)==max(i,j)) return DIST(n-2,n-1)+DIST(min(i,j),n-1);
    if(ans>0) return ans;    
    ans=min(dp(i+1,j)+DIST(i,i+1),dp(i+1,i)+DIST(i+1,j));
    return ans;
}

int main() {
#define LOCAL
#ifdef LOCAL
    freopen("uva1347.in","r",stdin);
#endif
    while(scanf("%d",&n)==1)
    {
        MM(x,0);
        MM(y,0);
        MM(d,0);
        int i=0;
        while(i<n) {
            scanf("%d %d",x+i,y+i);
            i++;
        }
        printf("%.2f\n",dp(0,0));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值