UVA - 1347 Tour

题目地址:点击 UVA 1347 链接


样例输入: 

3

1 1

2 3

3 1

4

1 1

2 3

3 1

4 2

样例输出:

6.47 

7.89


题意:  给你n个点  你的任务是求出从最左边点到最右边点 再从最右边点 回来的最短路径  (要求没个点都要走一遍)    。。

思路: dp[i][j]   我们假设同时有两个人在走  那么,两个人走的 路径不同 ,但是尽量短的走 ,那么走到两个人都走到第n个点,就会出现一个最短路径。我们假设两个人的当前位置分别是 i 和 j  那么dp[i][j]  看可以转移到  dp[i+1][j] 和 dp[i+1][i]  两种状态。分别表示  i 走到i+1  和 j  走到  i+1  个点。。 (注意  j 走到i+1  本应该转移到dp[i][i+1]  但是 我们 规定  i>j  其实也是为了 更好的去求解。 )  

那么初始状态  就是dp[n][i](i>=1&&i<=n)  dp[n][i]=dis[n][i];  

那么状态转移方程我们也可以很好的推出来  因为dp[i][j] 可以转移到dp[i+1][j]  和dp[i+1][i]  两种状态 ,那么dp[i][j] 的状态当然也是由  dp[i+1][j]  he dp[i+1][i] 两种状态倒着退回来 。  dp[i][j]=min(dp[i+1][j]+dis[i+1][i],dp[i+1][i]+dis[j][i+1])


代码: 


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#define N 1005

using namespace std;

double dp[N][N];
double dis[N][N];

struct node
{
	int x,y;
}a[N];

int n;

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

void memdp()
{
	for(int i=1;i<=n;i++) dp[n][i]=dis[n][i];
	
	for(int i=n-1;i>=1;i--)
	{
		for(int j=1;j<=i;j++)
		{
			dp[i][j]=min(dp[i+1][j]+dis[i+1][i],dp[i+1][i]+dis[j][i+1]);
		}
	}
	
	printf("%.2f\n",dp[1][1]);
	return ;
}

void chushihua()
{
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=n;j++)
		{
			dp[i][j]=dis[i][j]=0.0;
		}
	}
	return ;
}

int main()
{
	while(cin>>n)
	{
		for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
		chushihua();
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				double dist=juli(i,j);
				dis[i][j]=dist;
			}
		}
		memdp();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值