codeforce #339(div2)C Peter and Snow Blower

本文介绍了一种计算多边形绕固定顶点旋转时扫过面积的方法,利用点积和叉积来求解点到线段的最短距离,并通过实例说明了如何用C++实现该算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Peter and Snow Blower

题意:有n(3 <= n <= 100 000)个点的一个多边形,这个多边形绕一个顶点转动,问扫过的面积为多少?

思路:开始就认为是一个凸包的问题,像poj2187求点对平方的最大值一样,但是有一个点是确定的(ps:这道题在div1里面可是A啊!这么复杂?),所以直接求解即可,时间复杂度也就O(n);还有就是怎么求多边形到确定点的最小距离呢?这就不只是暴力求点对之间的距离这么简单了。因为一个多边形绕一个点转动时,有时候是定点到边的距离,所以转化为了点到线段的最短距离,使用了向量点积和叉积的性质即可求解;还有注意使用int会爆了问题。。。WA了几次

#include<bits/stdc++.h>
using namespace std;
`#define inf 0x3f3f3f3f
const double PI = acos(-1.0);
struct point{
    int x,y;
    point(){}
    point(int _x,int _y){
        x = _x; y = _y;
    }
    long long operator *(const point &b)const{// 叉乘
        return (1LL*x*b.y - 1LL*y*b.x);
    }
    point operator -(const point &b)const{
        return point(x - b.x,y - b.y);
    }
    long long dot(const point &b){    //点乘
        return 1LL*x*b.x + 1LL*y*b.y;
    }
    double dist(const point &b){
        return sqrt(1LL*(x-b.x)*(x-b.x)+1LL*(y-b.y)*(y-b.y));
    }
    long long dist2(const point &b){
        return 1LL*(x-b.x)*(x-b.x)+1LL*(y-b.y)*(y-b.y);
    }
    double len(){
        return sqrt(1LL*x*x+1LL*y*y);
    }
    void input(){
        scanf("%d%d",&x,&y);
    }
};

double point_to_segment(point a,point b,point c)//点a到“线段” bc的距离
{
    point v[4];
    v[1] = {c.x - b.x,c.y - b.y};
    v[2] = {a.x - b.x,a.y - b.y};
    v[3] = {a.x - c.x,a.y - c.y};
    if(v[1].dot(v[2]) < 0) return v[2].len();
    if(v[1].dot(v[3]) > 0) return v[3].len();
    return fabs(1.*(v[1]*v[2])/v[1].len());
}
const int MAXN = 1e5+10;
point p[MAXN];
int main()
{
    int n,i;
    cin>>n;
    for(i = 0;i <= n;i++){
        p[i].input();
    }
    p[++n] = p[1];
    double mx = 0.0,mn = 1.*inf;
    for(i = 1;i < n;i++){
        mx = max(mx,p[0].dist(p[i]));
        mn = min(mn,point_to_segment(p[0],p[i],p[i+1]));
    }
    printf("%.12f\n",PI*(mx*mx - mn*mn));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值