杭电OJ2073 无限的路(已AC,超详细解释,适合初学者)

题目就不贴了,就放个图方便大家打草稿示意杭电OJ2073 无限的路(已AC,超详细解释,适合初学者)_第1张图片
先别急着看代码,把思路捋清楚。
##首先题目是求两点的距离,我们可以先求出第一个点到原点的距离,再求出第二个点到原点的距离,然后两者相减即可,重要的是求出距离公式,就ok了。(注:这里的到原点距离是指中途所经过的所有线段的长度和,不是直接求到原点距离哦233别搞错了)

##递推过程:可以发现,图中的线段长度除了(0,0)->(0,1)长度是1,其他的只有两种,一种是斜率为-1的线段,一种是斜率为-2的线段,分别可以用m=sqrt((i-1) * (i - 1)+(i-1) * (i-1))和n=sqrt(i * i+(i-1) * (i-1))来表示,因为(0,0)->(0,i)的距离可以表示为(0,0)->(0,i-1)+(0,i-1)->(i-1,0)+(i-1,0)->(0,i),自己看图走一遍就懂了,用f(i)表示(0,0)->(0,i)的距离,则(0,0)->(0,i-1)的距离为f(i-1),其中f(1)=1,而(0,i-1)->(i-1,0)即为m,(i-1,0)->(0,i)即为n,于是每个y轴上的点(0,i)到原点距离的递推关系式就出来了:
f(i)=f(i-1)+m+n ;f(1)=1
再观察图中的点,发现不在坐标轴上的点都有一个特点,就是同一条线上的x+y相等
所以如果要求的是(x,i)到原点的距离的话,等价于求(0,x+i)到原点的距离即f(x+i)再加上x*sqrt(2.0)即可(观察图就可以得到,横坐标每增加1,长度增加根号2,别说你看不出来233)实在不懂就举个例子,就明白了,实践出真知。

#综上:点(x,y)到原点的距离公式为d=f(x+y)+x*sqrt(2.0)
公式出来了就直接套用就可以了,代码没什么难的,AC代码如下

#include
#include
#include
double f[210];
double dabiao()//有公式了就先打表一下,就是提前计算好,下面代入点(x,y)的时候可以直接调用
{
	f[1]=1;
	for(int i=2;i<=200;i++)
	{
		double m,n;
		m=sqrt((i-1)*(i-1)+(i-1)*(i-1));
		n=sqrt(i*i+(i-1)*(i-1));
		f[i]=f[i-1]+m+n;
	}//有不明白的见上面解析
	return 0;
}

double distance(int x,int y)
{
	double d=0;
	d=f[x+y]+x*sqrt(2.0);
	return d;
}//点(x,y)到原点的距离公式

int main()
{
	int x1,y1,x2,y2,n;
	double d1,d2,d;
	dabiao();
	while(scanf("%d",&n)!=EOF)
	{
	while(n--)
	{
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		d1=distance(x1,y1);
		d2=distance(x2,y2);
		d=d1-d2;
		if(d<0) d=-d;
		printf("%.3lf\n",d);
	}
	}
	return 0;
}

这次文字讲解很多,虽然很啰嗦,但是自己还是很用心的讲到每一个点了,因为自己当时也是想了好久才想通,所以希望可以尽可能的清楚地讲解给大家,同时也算是巩固一下自己吧。

你可能感兴趣的:(杭电OJ,算法)