首页 > 学院 > 开发设计 > 正文

path

2019-11-06 09:11:20
字体:
来源:转载
供稿:网友

3510. 【NOip2013模拟11.5B组】最短路径(path) (File IO): input:path.in output:path.out

Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits  Goto PRoblemSet

Description

平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在Zxd想要知道在每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强迫症患者,他有许多奇奇怪怪的要求与限制条件:1.  从 A 走到 B 时,只能由横坐标小的点走到大的点。2.  由 B 回到 A 时,只能由横坐标大的点走到小的点。3.  有两个特殊点 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-1 到 0 的路上。请你帮他解决这个问题助他治疗吧!

Input

第一行三个整数 n,b1,b2,( 0 < b1,b2 < n-1 且 b1 <> b2)。n 表示点数,从 0 到 n-1 编号,b1 和 b2 为两个特殊点的编号。以下 n 行,每行两个整数 x、y 表示该点的坐标(0 <= x,y <= 2000),从 0 号点顺序给出。Doctor Gao为了方便他的治疗,保证所有点横坐标不同,并且已经将给出的点按 x 增序排好了。

Output

仅一行,输出最短路径长度(精确到小数点后面 2 位)

Sample Input

5 1 31 33 44 17 58 3

Sample Output

18.18【样例解释】    最短路径:0->1->4->3->2->0

Data Constraint

20%的数据n<=2060%的数据n<=300100%的数据n<=1000

对于所有数据x,y,b1,b2如题目描述.

#include<iostream>#include<cstdio>#include<cmath>using namespace std;int a,b,c,d,e,v[2001][2];double r[2001][2001],f[2001][2001],ans;double dp(int,int);int main(){	freopen("path.in","r",stdin);	freopen("path.out","w",stdout);	scanf("%d%d%d",&a,&b,&c);	b++;	c++;	for (d=1;d<=a;d++)		scanf("%d%d",&v[d][1],&v[d][2]);	for (d=1;d<=a-1;d++)		for (e=d+1;e<=a;e++)			r[d][e]=sqrt((v[d][1]-v[e][1])*(v[d][1]-v[e][1])+(v[d][2]-v[e][2])*(v[d][2]-v[e][2]));	for (d=1;d<=a;d++)		for (e=1;e<=a;e++)			f[d][e]=-1;	ans=dp(1,1);	printf("%.2lf",ans);}double dp(int i,int j){	int k;	if (f[i][j]==-1)	{		if (i>j)			k=i;		else			k=j;		if (k==a)			f[i][j]=0;		else		{			if (k+1==b)			f[i][j]=r[i][b]+dp(b,j);            	else            if (k+1==c)             f[i][j]=r[j][c]+dp(i,c);            	else            if (k+1==a)             f[i][j]=r[i][a]+r[j][a]+dp(a,a);        		else            f[i][j]=min(r[i][k+1]+dp(k+1,j),r[j][k+1]+dp(i,k+1));		}	}	return f[i][j];}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表