ACM集训之入门训练赛一:几何题目 (CodeForce 614C Peter and Snow Blower)

版权声明:本文为博主原创文章,转载请注明出自CSDN Authur丶gyc。 https://blog.csdn.net/WHY995987477/article/details/88581710

Peter and Snow Blower(CodeForce 614C\CodeForce613A)
洛谷上的链接:https://www.luogu.org/problemnew/show/CF613A

题目大意

给你好多个点,这些点依次连起来形成一个多边形,这个多边形绕着多边形外面的一个定点旋转一周,问这个多边形扫过的面积为多少。
也就是求大圆减去小圆的面积。

思路

这里只要求出大圆的半径和小圆的半径,再注意精度的问题,就可以算出答案。
大圆的半径容易知道,就是所有的点中,离给出的定点最远的那个点。
但是最近的那个点有两种情况,一种是这个点就是在给出的点中,一种是这个最近的点在点与点的连线上。
这里还要算出点到所有边(线段)的垂线的距离。

算垂线的距离要分情况,我们要求的是到线段的距离,不是到直线的距离。所以如果定点与另外两个点所形成的三角形是钝角三角形,那么这个定点到这个线段的距离就等于定点到第一个点的距离或者定点到第二个点的距离。具体是哪条就要看哪个底角是钝角。
如果形成的不是钝角三角形,也就是两个底角都是锐角或有一个是直角,那么直接用点到直线的距离公式求解即可。

这里的PI出于保险取多了几位,为了避免遇到精度问题

反思

第一次遇到几何题目,又新奇又兴奋,一个劲的做结果没做出来。
因为考虑问题的时候一直考虑少情况了。
实际上如果这道题目写在一张纸上,不要求用代码实现,就给数据然后手算,我觉得初中生都能做出来。
所以觉得做题得多联系其他知识。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define pi 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491
using namespace std;
int n;
double x[100005],y[100005];
double sx,sy;
double point_dis_pow[100005];
double line_dis_pow[100005];
double d_pow[100005];
int main()
{
	scanf("%d %lf %lf",&n,&sx,&sy);
	//最小值不一定是距离最近的点,任取相邻两点,求点到线段的最短的距离
	//判断底角是否为钝角,是钝角就去两个距离的小值,都为锐角就取点到直线的距离 
 	//判断是否是钝角
 	for(int i=0;i<n;i++)
 		scanf("%lf %lf",&x[i],&y[i]);
 	for(int i=0;i<n;i++){
		point_dis_pow[i]=pow(sx-x[i],2)+pow(sy-y[i],2);//起点到顶点的平方 
		line_dis_pow[i]=pow(x[i]-x[(i+1)%n],2)+pow(y[i]-y[(i+1)%n],2);//两点线段距离的平方 
	}
	//最短的距离,可能是与顶点,可能是与线段,故求点到线段的最短距离
	//判断底角是否为钝角,存在一个钝角就是min点到顶点的距离 ,都不为钝角则是点到线段的距离
	for(int i=0;i<n;i++)
	{	//如果底角是钝角
		if(point_dis_pow[i]+line_dis_pow[i]<=point_dis_pow[(i+1)%n]||point_dis_pow[(i+1)%n]+line_dis_pow[i]<=point_dis_pow[i])
		{
			d_pow[i]=min(point_dis_pow[i],point_dis_pow[(i+1)%n]);
		}	
		else//起点到线段的垂线的距离,因为底角不是钝角,垂线必定在线段上,用点到直线距离公式即可求 
		{
			double A=y[(i+1)%n]-y[i];
			double B=-x[(i+1)%n]+x[i];
			double C=(-y[(i+1)%n]+y[i])*x[i]+(x[(i+1)%n]-x[i])*y[i];
			d_pow[i]=pow(A*sx+B*sy+C,2)/(A*A+B*B);
			//printf("d_pow:%.18lf\n",d_pow[i]);
		}
	//	printf("d_pow:%.18lf\n",d_pow[i]);
	}
	sort(d_pow,d_pow+n);
	sort(point_dis_pow,point_dis_pow+n);
	double maxn=point_dis_pow[n-1];
	double mini=d_pow[0];
//	printf("maxn=%lf mini=%lf\n",maxn,mini);
	double S=pi*(maxn-mini);
	printf("%.18lf\n",S);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/WHY995987477/article/details/88581710