cf#339-C - Peter and Snow Blower-简单几何

http://codeforces.com/contest/614/problem/C



给出一个n边形,求把多边形 通过一条线,绑在一个点上,绕这个点旋转,所扫过的面积。 (P点一定在多边形外部)

 

给出n个点端点;


直接求出离P最远的一个点,这个点到P的距离就是多边形能扫过的最大圆的半径(外圆)

然后求多边形的n-1条边(注意,是线段,不是直线) 到 p点的距离,取最短的,就是 多边形扫过的  最短半径(内圆)


pi*(max*max-min*min)就是答案

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
double min(double a, double b)
{return a<b?a:b;}
struct POINT
{
    double x;
    double y;
    POINT(double a=0, double b=0) { x=a; y=b;}
};
struct LINESEG
{
    POINT s;
    POINT e;
    LINESEG(POINT a, POINT b) { s=a; e=b;}
    LINESEG() { }
};
__int64 n,m; 
const double pi=acos(-1.0);

double dist(POINT p1,POINT p2)		//2点距离
{
    return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );
}
double dotmultiply(POINT p1,POINT p2,POINT p0)	//
{
	return ((p1.x-p0.x)*(p2.x-p0.x) + (p1.y-p0.y)*(p2.y-p0.y));
}
double relation(POINT c,LINESEG l)	//点线关系
{
	LINESEG tl;
	tl.s=l.s;
	tl.e=c;
	return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e));
}
POINT perpendicular(POINT p,LINESEG l)	
{
	double r=relation(p,l);
	POINT tp;
	tp.x=l.s.x+r*(l.e.x-l.s.x);
	tp.y=l.s.y+r*(l.e.y-l.s.y);
	return tp;
}
double ptolinesegdist(POINT p,LINESEG l,POINT &np)//求点p到线段的最近点
{
	double r=relation(p,l);
	if(r<0)
	{
		np=l.s;
		return dist(p,l.s);
	}
	if(r>1)
	{
		np=l.e;
		return dist(p,l.e);
	}
	np=perpendicular(p,l);
	return dist(p,np);
}
POINT tm[100005];
int main()
{
    
    __int64 x,y;
    int i,j;
    __int64 px,py;
    scanf("%I64d%I64d%I64d",&n,&px,&py);
    double minn= 10000000000000000 ;
    double maxx=0; 
	for (i=1;i<=n;i++)
	{
		scanf("%I64d%I64d",&x,&y); 
		x-=px;
		y-=py;
		tm[i]=POINT(x,y);
		double tmp=x*x+y*y;    
		if (tmp>maxx)
			maxx=tmp;  
	}
	tm[n+1]=tm[1];
	POINT p0(0,0);
	POINT closed;
	for (i=1;i<=n;i++)
	{
        LINESEG s1(tm[i],tm[i+1]);
        closed=ptolinesegdist(p0,s1,closed);
        double tmp_min=dist(closed,p0);
        minn=min(minn,tmp_min*tmp_min);
		
    }
	printf("%.7lf\n",pi*(maxx-minn));
	
	
	
	return 0;
	
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值