Tour UVA - 1347
题意:
给你n个点(按照x的递增序列给出),你的目标是从设计一条路线,从最左边的点出发,之后到达最右边的点,之后再返回。要求除了最左点和最右的点,每个点只经过一次。
思路:
- 用 d ( i , j ) d(i,j) d(i,j)表示1~ m a x ( i , j ) max(i,j) max(i,j)全部走过,且两个人的当前位置分别是 i i i和 j j j,还需要走多长的距离。
- 不难发现 d ( i , j ) = d ( j , i ) d(i,j)=d(j,i) d(i,j)=d(j,i),因此从现在开始规定在状态中 i > j i>j i>j。这样,不管是哪个人,状态 d ( i , j ) = m i n ( d ( i + 1 , j ) , d ( i + 1 , i ) ) d(i,j)=min(d(i+1,j),d(i+1,i)) d(i,j)=min(d(i+1,j),d(i+1,i))
- 边界是 d ( n − 1 , j ) = d i s t ( n − 1 , n ) + d i s t ( n , j ) d(n-1,j)=dist(n-1,n) +dist(n,j) d(n−1,j)=dist(n−1,n)+dist(n,j)
- ans = d i s t ( 1 , 2 ) = d ( 2 , 1 ) dist(1,2)=d(2,1) dist(1,2)=d(2,1)
AC
#include <iostream>
#include <bits/stdc++.h>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fori(i,x,y) for(int i=(x); i<(y); i++)
#define rep(i,y,x) for(int i=(y); i>=(x); i--)
#define mst(x,a) memset(x,a,sizeof(x))
#define pb push_back
#define sz(a) (int)a.size()
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>pai;
struct point{
int x, y;
} p[1010];
const int INF = 0x3f3f3f3f;
double d[1010][1010];
int n;
double dist(point p1, point p2){
double res = sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
return res;
}
double dp(int i, int j){
double& ans = d[i][j];
if(ans != INF)return ans;
if(i == n-1)return dist(p[n-1],p[n])+dist(p[n],p[j]);
else return ans = min(dp(i+1,j) + dist(p[i],p[i+1]), dp(i+1,i) + dist(p[j],p[i+1]));
}
int main()
{
while(~scanf("%d", &n)){
For(i,0,n)For(j,0,n) d[i][j] = INF;
For(i,1,n) scanf("%d%d", &p[i].x, &p[i].y);
double ans = dp(2,1) + dist(p[1],p[2]);
printf("%.2f\n", ans);
}
return 0;
}