zufe 2432 圆覆盖

问题 K: 圆覆盖

时间限制: 1 Sec   内存限制: 256 MB
提交: 64   解决: 12
[ 提交][ 状态][ 讨论版]

题目描述

题解:
找一个圆,枚举圆中的纵坐标,对于每个圆循环一次求区间的并。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll x[102],y[102],r[102];
ll abs1(ll k)
{
    if(k<0)return -k;
    return k;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld%lld",&x[i],&y[i],&r[i]);
    ll ans=0;
    for(ll i=y[1]+r[1];i>=y[1]-r[1];i--)
    {
        ll l2=1.00*x[1]-sqrt(1.00*r[1]*r[1]-1.00*(i-y[1])*(i-y[1]));
        ll r2=1.00*x[1]+sqrt(1.00*r[1]*r[1]-1.00*(i-y[1])*(i-y[1]));
        l2-=1;r2+=1;
        while(r[1]*r[1]-(i-y[1])*(i-y[1])<(l2-x[1])*(l2-x[1]))
            l2++;//控制精度。
        while(r[1]*r[1]-(i-y[1])*(i-y[1])<(r2-x[1])*(r2-x[1]))
            r2--;
        bool bb=1;
        for(int j=2;j<=n;j++)
        {
            if(i>y[j]+r[j]||i<y[j]-r[j])
            {
                bb=0;break;
            }
            ll k=abs1(i-y[j]);
            ll l1=1.00*x[j]-sqrt(1.00*r[j]*r[j]-1.00*k*k);
            ll r1=1.00*x[j]+sqrt(1.00*r[j]*r[j]-1.00*k*k);
            l1-=1;r1+=1;
            while(r[j]*r[j]-(i-y[j])*(i-y[j])<(l1-x[j])*(l1-x[j]))
               l1++;
            while(r[j]*r[j]-(i-y[j])*(i-y[j])<(r1-x[j])*(r1-x[j]))
               r1--;
            if(r1<l2||l1>r2)
            {
                bb=0;break;
            }
            l2=max(l2,l1);
            r2=min(r2,r1);
        }
        if(bb&&r2>=l2) ans+=r2-l2+1;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/albertluf/article/details/80377835