您的位置:首页 > 其它

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

2015-08-27 15:35 351 查看
题意:

平面上有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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息