规定从最左边的点出发以简化问题,然后严格向右直至最右边的点,再从最右边的点走到最左点,保证途径所有点各一次(除了最左点)且路径最小。
用dp(i,j)表示A走到i,B走到j时的状态还需要走多远到终点(注意表示的是还有多少到终点,所以其结果与前面怎么走的无关),所以必然dp(i,j)==dp(j,i);
规定dp(i,j)规定为:A在i,B在j(i>=j)且i之前的所有点都走过了。
那么dp[i][j] = min(DP(i + 1, j) + dist(i, i + 1), DP(i + 1, i)+dist(j,i+1));
本来书上思路没看懂,感谢maxichu,http://www.aiuxian.com/article/p-2413402.html
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<ctype.h>
#include<algorithm>
#include<deque>
#include<functional>
#include<iterator>
#include<vector>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#define CPY(A, B) memcpy(A, B, sizeof(A))
typedef long long LL;
typedef unsigned long long uLL;
const int MOD = int (1e9) + 7;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-9;
const double OO = 1e20;
const double PI = acos (-1.0);
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
using namespace std;
struct point {
double x,y;
bool operator < (const point &s) const {return x<s.x;}
};
point p[1010];
double dp[1010][1010];
double dis[1010][1010];
double dist (int i,int j) {
if (dis[i][j]>=0) { return dis[i][j]; }
return dis[i][j]=sqrt ( (p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y) );
}
double DP (int i, int j){
if (dp[i][j] >= 0) { return dp[i][j]; }
dp[i][j] = min (DP (i+1,j) +dist (i,i+1),DP (i+1,i)+dist (j,i+1) );
return dp[i][j];
}
int main() {
int n;
while (cin>>n) {
memset (dp,-1,sizeof (dp) );
memset (dis,-1,sizeof (dis) );
for (int i=0; i<n; i++) {
scanf ("%lf%lf",&p[i].x,&p[i].y);
}
sort (p,p+n);
for (int j=0; j<n; j++) {
dp[n - 2][j] = dist (n - 2, n - 1) + dist (j, n - 1);
}
printf ("%.2f\n",DP (0,0) );
}
return 0;
}