UVa1347 Tour(DP)

Tour

给定平面上n(n<=1000)个点的坐标(按照x递增的顺序给出。各点x坐标不同,且均为整数),你的任务是设计一条路线,从最左边的点出发走到最右边的点再返回,要求除了最左边和最右边之外,每个点恰好经过一次,且路径总长度最短,两点间的长度为它们的欧几里得距离。

状态定义:dp(i,j)表示1~max(i,j)全部走过,且两个人的当前位置分别是i和j,还需要走多长的距离 。

不难发现dp(i,j)=dp(j,i),因此从现在开始规定在状态中i>j。这样,不管是那个人,下一步只能走到i+1,i+2,…这些点。可是,如果走到i+2,情况变成了“1~i和i+2,但是i+1没走过”,无法表示成状态!怎么办?禁止这样的决策!也就是说,只允许其中一个人走到i+1,而不能走到i+2,i+3,…。
换句话说,状态dp(i,j)只能转移到dp(i+1,j)或者dp(i,i+1)(由于i>j,而dp(i,j)=dp(j,i)),所以 状态dp(i,j)只能转移到dp(i+1,j)或者dp(i+1,i) 。

边界条件 :dp(n-1,j)=dist(n-1,n)+dist(j,n)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

int n;
struct node {
	double x,y;
} a[1005];

double dp[1005][1005];

double dist(int i,int j) {
	return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}

//dp(i,j)表示1~max(i,j)全部走过,且两个人的当前位置分别是i和j,还需要走多长的距离 。
//dp[i][j]=dp[j][i]
double solve(int i,int j) {//记忆化搜索时保证i>j 
	if(dp[i][j]>0)
		return dp[i][j];
	return dp[i][j] = min(solve(i+1,j)+dist(i,i+1),solve(i+1,i)+ dist(j,i+1));
}

int main() {
	double ans;
	while(cin>>n) {
		for(int i=1; i<=n; i++) {
			cin>>a[i].x>>a[i].y;
		}
		memset(dp,0,sizeof(dp));
		for(int i=1; i<n-1; i++) {
			dp[n-1][i]=dist(n-1,n)+dist(i,n);
		}
		ans=solve(1,1);
		printf("%.2f\n",ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值