题目大意:给你一个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. Windows游戏找不到了怎么办?

         大家有的时候,可能是不慎操作,或是某些新装的Windows,会发现那些经典的游戏不见了,那它们去哪了呢?是长腿跑了?还是Windows偷工减料?都不是,让巩固来教你们把他们找出来! 1.在开 ...

  2. Jsp的语法和指令

    Jsp的三种注释 前端语言注释:<!-- --> 会被转译,也会被发送,但是不会被浏览器执行 java语言注释: 会被转译,但是不会被servlet执行 Jsp注释:<%--  -- ...

  3. BeautifulSoup基本步骤

    http://blog.csdn.net/kikaylee/article/details/56841789 ’BeautifulSoup是Python的一个库,最主要的功能就是从网页爬取我们需要的数 ...

  4. linux常见命令整理

    Linux管理文件和目录的命令 命令 功能 命令 功能 pwd 显示当前目录 ls 查看目录下的内容 cd 改变所在目录 cat 显示文件的内容 grep 在文件中查找某字符 cp 复制文件 touc ...

  5. Tensorflow currently has no official prebuild for your CUDA, cuDNN combination.

    INFO CUDA version: 10. ERROR cuDNN not found. See https://github.com/deepfakes/faceswap/blob/master/ ...

  6. KNN和K-Means的区别

    KNN和K-Means的区别 KNN K-Means 1.KNN是分类算法 2.监督学习 3.喂给它的数据集是带label的数据,已经是完全正确的数据 1.K-Means是聚类算法 2.非监督学习 3 ...

  7. D3_book 7 area

    <!-- area的例子csv使用node.js提供的 --> <!DOCTYPE html> <meta charset="utf-8"> & ...

  8. uniGUI试用笔记(九)uniGUI执行程序部署有3种形式1

    uniGUI执行程序部署有3种形式 1.ISAPI模式 部署在IIS或Apache,程序编译为Dll形式,没有试,准备后续专门测试一下. 2.标准执行文件模式 将软件编译成一个独立的Exe文件,包括了 ...

  9. Android SDK目录结构

    Android版本下载:从4.0到8.0版本: Android SDK目录结构图: sdk全称:software develop kits 软件开发工具集 add-ons:Google API map ...

  10. SQL SERVER 2014--学习笔记1

    --======================================================= 在SQL SERVER 2014中,最吸引眼球的就是内存表和本地编译存储过程,在MS ...