题目大意:给你一个m个点的简单多边形。对于每个点i∈[1,n],作一个以O点为原点且过点i的圆,求该圆在多边形内的圆弧长度/圆长。

其中n≤200,m≤500。

我们将n个点分开处理。

首先,我们要判断需处理的圆,是否被包含在多边形内,或者圆把多边形包含了。

我们显然可以从原点出发,向上作一条x=0的射线,判断该射线与多边形有多少个交点。

显然,若交点数量为奇数个,那么该点就在多边形内,否则在多边形外。

若圆与多边形存在交点,我们对多边形的每条边,求出其与圆,有多少个交点(0个,1个,2个,其实1个点可以当2个去处理)

这里就是简单地推个式子就可以求出,详见代码。

求出这些交点后,进行极角排序。

对于两个排序后相邻的点,我们要判断,由这两个点所构成的弧,是否被多边形包含。

有一种很暴力的思路,就是求出这两个点在弧上的中点,然后作一条从该点出发,向上作一条平行于x轴的射线,求这条射线与多边形的相交次数。

显然,若交点数量为奇数个,那么该点就在多边形内,否则在多边形外(和上面判断圆是否被包含的部分相同)。

对于每个圆,最多会出现2m个交点,最后单次判断两点所构乘的圆弧是否被多边形包含,需要O(m)的时间,则总时间复杂度为O(n*m^2)。

下面是一些需要注意的细节:

1,上述判断奇数偶数个点时,所做射线可能会经过多边形两条边的交点。考虑到输入的点全部都是整点,故对构成多边形的点集偏移2eps即可。

2,由于点要被多边形严格包含,那么在判断时,范围要向两边缩减eps。

思路简单,代码复杂,qwq....

(听说还卡精度)。。。

 #include<bits/stdc++.h>
#define M 505
#define DB long double
#define eps 1e-6
#define PI 3.14159265358979323846
using namespace std; bool zero(DB x){return fabs(x)<eps;}
struct pt{
DB x,y;
pt(){x=y=;}
pt(DB xx,DB yy){x=xx; y=yy;}
friend pt operator -(pt a,pt b){return pt(a.x-b.x,a.y-b.y);}
friend bool operator <(pt a,pt b){return atan2(a.y,a.x)<atan2(b.y,b.x);}
DB mo(){return x*x+y*y;}
}; struct line{
DB a,b,c;
line(){a=b=c=;}
line(DB aa,DB bb,DB cc){a=aa; b=bb; c=cc;}
line(pt A,pt B){
DB x1=A.x,y1=A.y;
DB x2=B.x,y2=B.y;
a=y1-y2; b=x2-x1;
c=-a*x2-b*y2;
}
}; pt a[M],b[M],c[M]; int n,m;
int type[M]={};
DB sita[M]={};
DB solve(pt hh){
memset(c,,sizeof(c));
memset(type,,sizeof(type));
int cnt=,ok=;
DB R=hh.x*hh.x+hh.y*hh.y,r=sqrt(R);
for(int i=;i<=m;i++){
line p=line(b[i],b[i+]);
if(fabs(p.c/sqrt(p.a*p.a+p.b*p.b))-eps<r) ok=;
DB xl=min(b[i].x,b[i+].x),xr=max(b[i].x,b[i+].x);
DB yl=min(b[i].y,b[i+].y),yr=max(b[i].y,b[i+].y);
xl-=eps; yl-=eps; xr+=eps; yr+=eps;
DB x1,x2,y1,y2; bool is0=;
if(zero(p.a)){
y1=y2=-p.c/p.b;
DB delta=R-y1*y1;
if(delta<-eps) continue;
if(zero(delta)) is0=;
x1=-sqrt(delta); x2=sqrt(delta);
}else{
DB A=p.b*p.b+p.a*p.a;
DB B=p.b*p.c*;
DB C=p.c*p.c-R*p.a*p.a;
DB delta=B*B-*A*C;
if(delta<-eps) continue;
if(zero(delta)) is0=;
y1=(-B+sqrt(delta))/(*A);
y2=(-B-sqrt(delta))/(*A);
x1=(-p.b*y1-p.c)/p.a;
x2=(-p.b*y2-p.c)/p.a;
}
int ok1,ok2;
if(xl<=x1&&x1<=xr&&yl<=y1&&y1<=yr){ c[++cnt]=pt(x1,y1); if(is0) continue;}
if(xl<=x2&&x2<=xr&&yl<=y2&&y2<=yr) c[++cnt]=pt(x2,y2);
}
if(ok){
//return 1;
c[cnt=]=pt(,);
}else{
sort(c+,c+cnt+);
for(int i=;i<=cnt;i++) sita[i]=atan2(c[i].y,c[i].x);
}
c[cnt+]=c[]; sita[cnt+]=sita[]+*PI;
DB ans=;
for(int i=;i<=cnt;i++){
double SITA=(sita[i]+sita[i+])/;
pt hh=pt(r*cos(SITA)+eps*,r*sin(SITA));
int cnt=;
for(int j=;j<=m;j++){
double l=b[j].x,r=b[j+].x;
if(zero(b[j].x-b[j+].x)) continue;
line p=line(b[j],b[j+]);
double y=-(p.a*hh.x+p.c)/p.b;
if(l>r) swap(l,r);
l+=eps; r-=eps;
if(l<=hh.x&&hh.x<=r&&y+eps>hh.y) cnt++;
}
if(cnt&) ans+=sita[i+]-sita[i];
}
ans/=(.*PI);
return ans;
} int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) cin>>a[i].x>>a[i].y;
for(int i=;i<=m;i++) cin>>b[i].x>>b[i].y;
b[m+]=b[];
DB ans=;
for(int i=;i<=n;i++){
ans+=solve(a[i]);
//printf("%.5Lf\n",ans);
}
double res=ans;
printf("%.5lf\n",res);
}

【loj6437】 【PKUSC2018】 PKUSC 计算几何的更多相关文章

  1. LOJ6437 PKUSC2018 PKUSC

    带劲的计算几何[这一定是我WC之前开的最后一道计几!!! 每个点画个圆然后看一下交点 然后判断是多边形内还是多边形外 这个就是取圆上中点然后射线法 eps我1e-8才过 不知道为啥有的人说只能开1e- ...

  2. LOJ6437. 「PKUSC2018」PKUSC [计算几何]

    LOJ 思路 显然多边形旋转可以变成点旋转,不同的点的贡献可以分开计算. 然后就变成了要求一个圆在多边形内的弧长. 考虑把交点全都求出来,那么两个交点之间的状态显然是相同的,可以直接把圆弧上的中点的状 ...

  3. loj#6437. 「PKUSC2018」PKUSC(计算几何)

    题面 传送门 题解 计算几何的东西我好像都已经忘光了-- 首先我们可以把原问题转化为另一个等价的问题:对于每一个敌人,我们以原点为圆心,画一个经过该点的圆,把这个圆在多边形内部的圆弧的度数加入答案.求 ...

  4. [LOJ#6437][BZOJ5373]「PKUSC2018」PKUSC

    [LOJ#6437][BZOJ5373]「PKUSC2018」PKUSC 试题描述 九条可怜是一个爱玩游戏的女孩子. 最近她在玩一个无双割草类的游戏,平面上有 \(n\) 个敌人,每一个敌人的坐标为 ...

  5. 【LOJ】#6437. 「PKUSC2018」PKUSC

    题解 我们把这个多边形三角形剖分了,和统计多边形面积一样 每个三角形有个点是原点,把原点所对应的角度算出来,记为theta 对于一个点,相当于半径为这个点到原点的一个圆,圆弧上的弧度为theta的一部 ...

  6. [LOJ6437]PKUSC

    旋转多边形是没有前途的,我们考虑旋转敌人,那么答案就是所有人的可行区间长度之和除以$2\pi$ 首先对每个敌人找到那些旋转后会落到多边形上的角度,实际上就是圆和一些线段求交,解方程即可,注意判一下落在 ...

  7. 「PKUSC2018」PKUSC

    传送门 Solution  考虑求每个点的贡献 等价于一个以OA长为半径的圆心为原点的圆在多边形内的弧对应的角度/\(2\pi\) 求弧度可以利用三角剖分 在原点的点要特判,采用射线法就可以了 Cod ...

  8. LOJ#6437. 「PKUSC2018」PKUSC

    题面 题意转化为: 判断每个点所在的圆有多长的弧度角位于多边形内部. 然后就很暴力了. 每个点P,直接找到多边形和这个圆的所有交点,按照距离P的角度排序. 找交点,直接联立二元二次方程组.... 需要 ...

  9. 「PKUSC2018」星际穿越 (70分做法)

    5371: [Pkusc2018]星际穿越 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 27  Solved: 11[Submit][Status] ...

随机推荐

  1. "我们分手吧。"女的对男的说。 "为什么呢?亲爱的,你不要我了么?" "因为你幼稚。"女的坚定地语气回答道,然后转身准备走。 男的上前踩住女的影子,然后说...

    1."我们分手吧."女的对男的说. "为什么呢?亲爱的,你不要我了么?" "因为你幼稚."女的坚定地语气回答道,然后转身准备走. 男的上前踩 ...

  2. 2018.07.17 HAOI2016 找相同字符(SAM)

    传送门 就是给两个字符串,让你求公共字串的个数. 本来大佬们都是用的广义后缀自动机,但我感觉后缀自动机已经可以做这道题了.我们对其中一个字串建出后缀自动机,然后用另外一个后缀自动机在上面统计贡献即可. ...

  3. UVa 11292 Dragon of Loowater (水题,排序)

    题意:有n个条龙,在雇佣勇士去杀,每个勇士能力值为x,只能杀死头的直径y小于或等于自己能力值的龙,只能被雇佣一次,并且你要给x赏金,求最少的赏金. 析:很简单么,很明显,能力值高的杀直径大的,低的杀直 ...

  4. DOM数据解析

    //DOM : Document Object Model ,一种XML解析的方式,先读取整篇的内容,然后再进行解析,解析速度比较快,如果内出现错误,解析就会失败,iOS不支持DOM解析,goole提 ...

  5. (并查集 建立关系)食物链 -- POJ-- 1182

    链接: http://poj.org/problem?id=1182 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82830#probl ...

  6. VMware Workstation 12 OpenGL ES版本支持情况与设置

    概述 开始学习Opengl时,发现VMware Workstation虚拟机无法运行Opengl ES2.0的程序.后来,经过查找最终得知,是因为VMware Workstation11及之前的版本对 ...

  7. Codeforces801C Voltage Keepsake 2017-04-19 00:26 109人阅读 评论(0) 收藏

    C. Voltage Keepsake time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  8. Linux 用 sftp scp命令 互传文件

    sftp它类似于 ftp, 但它进行加密传输,比FTP有更高的安全性. sftp 是SSH服务的子程序 常用命令 pwd 查看当前工作目录 ls 查看远程当前目录下的所以文件或者目录信息 lls 查看 ...

  9. nodejs 上传文件 upload

    只是现在主要用nodejs做后端了,所以记录一些上传文件的使用方法. 上传文件的主要方式: 1.form上传,优点是方便,缺点是没法回调,上传后返回的数据没法处理 2.ajax上传,优点是可控制,有回 ...

  10. python的数据存储

    Python存储数据 使用json.dump()和json.load() 不管专注的是什么,程序都把用户提供的信息存储在列表和字典等数据结构中.用户关闭程序时,你几乎总是要保存他们提供的信息:一种简单 ...