题目大意:给定n个坐标(x,y),按照x地等的顺序给出, 并且保证x都不相同,均为正整数。你的任务是设计一条路线,从最左侧出发,达到最右侧, 再返回最左侧那个点,所有点恰好经过一次。并且总路线距离长度最短。
解题思路:可以认为从左左侧有两个人出发,每个人除了最左侧和最右侧的点外不会走相同的点,假设两个人走到的点分别为i, j(横坐标x)。dp(i, j)表示从1~max(i, j)的点都走过。dist表示距离最右侧的点的距离。那么每走一个点都有两个状态,在i的人走到下一个还是在j的走到下一个,由于不好判断下一个的坐标,并且dp(i, j) == dp (j, i), 因此我们不妨让i总是大于j。 那么下一个坐标就是i+1; 两个状态分别为, 走在前面的到达下一个点 dp(i+1, j), 或者走在后面的到下一个dp(i+1, i)。(解释:最大的肯定时i+1, 所以不管怎么走都是 dp(i, x), 如果走在前面的那个人走, 那么小的那个人还是在j, 如果在后面的到达i+1, 那么后面的人就变成了在i的那个人)。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
double distance(int x1, int y1, int x2, int y2)
{
double x = fabs(x1-x2);
double y = fabs(y1-y2);
return sqrt(x*x + y*y);
}
int X[1050], Y[1050];
double dist[1050][1050];
int n;
double dp(int i, int j)
{
if(dist[i][j] > 0) return dist[i][j];
if(i >= n-1) return dist[i][j] = distance(X[n-1], Y[n-1], X[j], Y[j]);
return dist[i][j] = min(dp(i+1, j)+distance(X[i+1], Y[i+1], X[i], Y[i]), dp(i+1, i)+distance(X[i+1], Y[i+1], X[j], Y[j]));
}
int main()
{
while(scanf("%d", &n) != EOF && n)
{
memset(dist, 0, sizeof(dist));
for(int i=0; i<n; i++)
scanf("%d%d", &X[i], &Y[i]);
printf("%.2f\n", dp(0, 0));
}
return 0;
}