bzoj 1913: [Apio2010]signaling 信号覆盖【旋转卡壳(?)】

参考:https://blog.csdn.net/qpswwww/article/details/45334033 讲的很清楚

做法比较像旋转卡壳但是具体是不是我也不清楚..
首先知道只要求出每种方案在圆上和圆中的和就可以。
注意到题目中有一个限制:“保证任何三个房子都不在同一条直线 上,任何四个房子都不在同一个圆上。”,所以考虑构成圆的三个点和需要判断的第四个点组成的四边形:
对于凹四边形,只有一种情况,第四个点一定在圆内;
对于凸四边形,第四个点可能在园中,圆上,圆外,其中园中,圆上是符合条件的。
又,总的四边形个数是\( C_n^4 \),所以只求得凸四边形的个数即可。
把凸四边形看做一个三角形中有一个点,现在需要找出没有覆盖这个点的三角形,枚举中间这个点,然后把其他点按这个点极角排序,枚举三角形上的一个点,用旋转卡壳一样的东西取卡另外两个点的可选区间,然后用\( C_{n-1}^3 \)减去这个数加进ans里即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=3005;
int n;
long long ans;
double p[N];
struct dian
{
    double x,y;
    dian(double X=0,double Y=0)
    {
        x=X,y=Y;
    }
    dian operator - (const dian &a) const
    {
        return dian(x-a.x,y-a.y);
    }
}a[N];
long long C(long long n,long long m)
{
    long long r=1ll,c=1ll;
    for(int i=0;i<m;i++)
        r*=(n-i);
    for(int i=1;i<=m;i++)
        c*=i;
    return r/c;
}
void wk(int x)
{
    int top=0;
    for(int i=1;i<=n;i++)
        if(i!=x)
            p[++top]=atan2((a[i]-a[x]).y,(a[i]-a[x]).x);
    sort(p+1,p+1+top);
    long long con=0;
    for(int i=1;i<n;i++)
        p[++top]=p[i]+2*M_PI;
    int w=1;
    for(int i=1;i<n;i++)
    {
        w=max(w,i+1);
        while(w<=top&&p[w]<p[i]+M_PI)
            w++;
        if(w-i-1>=2)
            con+=C(w-i-1,2);
    }
    ans+=C(n-1,3)-con;
}
int main()
{
    scanf("%d",&n);
    if(n<=3)
    {
        puts("0");
        return 0;
    }
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&a[i].x,&a[i].y);
    for(int i=1;i<=n;i++)
        wk(i);
    printf("%lf\n",(double)(ans+2*(C(n,4)-ans))/(double)C(n,3)+3.0);
    return 0;
}

转载于:https://www.cnblogs.com/lokiii/p/8834158.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值