列表

详情


NC15744. 小白兔小灰兔

描述

老山羊伯伯在地里收白菜,小白兔和小灰兔看见了就一起来帮忙。

他们干了半天,终于干完了。

羊伯伯:小灰兔,这车白菜送给你!

小灰兔:谢谢羊伯伯!

羊伯伯:小白兔,我也送你一车白菜!

小白兔:我不要白菜!给我一包白菜种子吧!

羊伯伯:好!给你~

小白兔:谢谢羊伯伯~

小灰兔把白菜拉到家里之后,就跟大家梦想中的生活一样,躺着啥都不干,吃吃吃,吃了玩~(好想一辈子都这样啊~小灰兔心想。)

小白兔把种子拿回去,打算开始勤劳地种白菜。然而他发现不是所有土地都能用来种白菜,只有被阳光照到的地方可以种白菜。

小白兔生活的星球可以看作二维平面中的一个简单多边形,太阳可以看作一个点。小白兔想知道,这个星球上一共有长度多少的土地可以用来种白菜。

输入描述

第一行是一个正整数T(≤ 20),表示测试数据组数,

对于每组测试数据,

第一行是一个整数n(3≤ n≤ 10),表示简单多边形的顶点数,

接下来n行,每行是两个整数xi,yi(-10≤ xi,yi≤10),按照逆时针绕向给出简单多边形的n个顶点的坐标,

最后一行是两个整数x,y(-10≤ x,y≤10),表示太阳的坐标,保证太阳在多边形外且不在多边形任意一条边所在直线上。

输出描述

对于每组测试数据,输出一行,包含一个实数,表示可以用来种白菜的土地的总长度,要求相对误差不超过

也就是说,令输出结果为a,标准答案为b,若满足,则输出结果会被认为是正确答案。

示例1

输入:

2
4
0 0
2 0
2 2
0 2
4 1
4
0 0
2 0
2 2
0 2
4 4

输出:

2.000000000000
4.000000000000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 3ms, 内存消耗: 424K, 提交时间: 2021-10-26 16:58:25

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define db double
const int N=100;
const db eps=1e-9,inf=1e18;
ll t,n,m;

int sign(db k) { return k<-eps? -1: (k>eps? 1: 0); }
struct poi
{
    db x,y;
    poi operator+(const poi& a) const { return poi{x+a.x,y+a.y}; }
    poi operator-(const poi& a) const { return poi{x-a.x,y-a.y}; }
    poi operator*(const db& k) const { return poi{x*k,y*k}; }
};
db Cro(poi a,poi b) { return a.x*b.y-a.y*b.x; }
db Dot(poi a,poi b) { return a.x*b.x+a.y*b.y; }
db Len(poi a) { return sqrt(Dot(a,a)); }

poi ps[N],s;

//返回切点占AB比例,距A比例
db divR(poi a,poi b,poi c,poi d)
{
    poi t1=a-b,t2=c-d,t3=a-c;
    if(sign(Cro(t1,t2))==0) return -inf;
    db ret = (Cro(t3,t2)) / (Cro(t1,t2));
    return sign(ret)>=0 && sign(ret-1)<=0 ? ret:-inf;
}

//判线段相交
bool pan_cross_LL(poi a,poi b,poi c,poi d)
{
    db c1=Cro(b-a,c-a),c2=Cro(b-a,d-a);
    db d1=Cro(d-c,a-c),d2=Cro(d-c,b-c);
    return sign(c1)*sign(c2)<=0 && sign(d1)*sign(d2)<=0;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>ps[i].x>>ps[i].y;
        ps[n+1]=ps[1];
        cin>>s.x>>s.y;
        db ans=0;
        for(int i=1;i<=n;i++)
        {
            vector<db> cp;
            for(int j=1;j<=n;j++)
            {
                db ins=divR(ps[i],ps[i+1],s,ps[j]);
                if(ins>=-1) cp.push_back(ins);
            }
            sort(cp.begin(),cp.end());
            db rate=0;
            for(int j=0;j<(int)cp.size()-1;j++)
            {
                poi cut=ps[i]+(ps[i+1]-ps[i])*((cp[j]+cp[j+1])/2);
                bool isok=0;
                for(int k=1;k<=n;k++)
                {
                    if(k==i) continue;
                    if(pan_cross_LL(s,cut,ps[k],ps[k+1]))
                    {
                        isok=1;break;
                    }
                }
                if(!isok) rate+=cp[j+1]-cp[j];
            }
            ans+=rate*Len(ps[i+1]-ps[i]);
        }
        cout<<fixed<<setprecision(12)<<ans<<"\n";
    }

    return 0;
}

上一题