【loj6437】 【PKUSC2018】 PKUSC 计算几何
题目大意:给你一个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 计算几何的更多相关文章
- LOJ6437 PKUSC2018 PKUSC
带劲的计算几何[这一定是我WC之前开的最后一道计几!!! 每个点画个圆然后看一下交点 然后判断是多边形内还是多边形外 这个就是取圆上中点然后射线法 eps我1e-8才过 不知道为啥有的人说只能开1e- ...
- LOJ6437. 「PKUSC2018」PKUSC [计算几何]
LOJ 思路 显然多边形旋转可以变成点旋转,不同的点的贡献可以分开计算. 然后就变成了要求一个圆在多边形内的弧长. 考虑把交点全都求出来,那么两个交点之间的状态显然是相同的,可以直接把圆弧上的中点的状 ...
- loj#6437. 「PKUSC2018」PKUSC(计算几何)
题面 传送门 题解 计算几何的东西我好像都已经忘光了-- 首先我们可以把原问题转化为另一个等价的问题:对于每一个敌人,我们以原点为圆心,画一个经过该点的圆,把这个圆在多边形内部的圆弧的度数加入答案.求 ...
- [LOJ#6437][BZOJ5373]「PKUSC2018」PKUSC
[LOJ#6437][BZOJ5373]「PKUSC2018」PKUSC 试题描述 九条可怜是一个爱玩游戏的女孩子. 最近她在玩一个无双割草类的游戏,平面上有 \(n\) 个敌人,每一个敌人的坐标为 ...
- 【LOJ】#6437. 「PKUSC2018」PKUSC
题解 我们把这个多边形三角形剖分了,和统计多边形面积一样 每个三角形有个点是原点,把原点所对应的角度算出来,记为theta 对于一个点,相当于半径为这个点到原点的一个圆,圆弧上的弧度为theta的一部 ...
- [LOJ6437]PKUSC
旋转多边形是没有前途的,我们考虑旋转敌人,那么答案就是所有人的可行区间长度之和除以$2\pi$ 首先对每个敌人找到那些旋转后会落到多边形上的角度,实际上就是圆和一些线段求交,解方程即可,注意判一下落在 ...
- 「PKUSC2018」PKUSC
传送门 Solution 考虑求每个点的贡献 等价于一个以OA长为半径的圆心为原点的圆在多边形内的弧对应的角度/\(2\pi\) 求弧度可以利用三角剖分 在原点的点要特判,采用射线法就可以了 Cod ...
- LOJ#6437. 「PKUSC2018」PKUSC
题面 题意转化为: 判断每个点所在的圆有多长的弧度角位于多边形内部. 然后就很暴力了. 每个点P,直接找到多边形和这个圆的所有交点,按照距离P的角度排序. 找交点,直接联立二元二次方程组.... 需要 ...
- 「PKUSC2018」星际穿越 (70分做法)
5371: [Pkusc2018]星际穿越 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 27 Solved: 11[Submit][Status] ...
随机推荐
- 2018.10.05 NOIP模拟 相遇(dfs序+lca)
传送门 考虑到两条路径相交的条件: 设两条路径为a,ba,ba,b. 则要么aaa路径的lcalcalca在bbb上. 要么bbb路径的lcalcalca在aaa上. 因此我们维护两棵树. 分别支持路 ...
- asp.net Hessian 服务的注册
Hessian服务端实现了IHttpHandle, 默认情况下是在Web.Config中的handles接点中注册,这样当有 很多实现时比较麻烦 这个时候可以实现IHttpHandleFactory注 ...
- 【转】Paxos算法3-实现探讨
——转自:{老码农的专栏} 前两篇Paxos算法的讨论,让我们对paxos算法的理论形成过程有了大概的了解,但距离其成为一个可执行的算法程序还有很长的路要走,原因是很多的细节和错误未被考虑.Googl ...
- sql笔试练习
转:http://www.360doc.com/content/16/0919/17/14804661_592046675.shtml 本文是在Cat Qi的参考原帖的基础之上经本人一题一题练习后编辑 ...
- C语言 fread()与fwrite()函数说明与示例
1.作用 读写文件数据块. 2.函数原型 (1)size_t fread ( void * ptr, size_t size, size_t count, FILE * stream ); 其中,pt ...
- 初探FFT(快速傅里叶变换)
第一次接触省选的知识点呢!zrf大佬在课堂上讲的非常清楚,但由于本蒟蒻实在太菜了,直接掉线了.今天赶紧恶补一下. 那么这篇博客将分为两块,第一块是FFT的推导和实现,第二块则是FFT在OI上的应用 因 ...
- 团队项目(第二周)—GG队
项目需求规格分析 队员信息 队员 学号 叶尚文(队长) 3116008802 蔡晓晴 3216008808 杜婷萱 3216008809 龙剑初 3116004647 于泽浩 3116004661 项 ...
- 四则运算 Java 实现 刘丰璨,王翠鸾
四则运算 GitHub仓库 功能实现 [x] 使用 -n 参数控制生成题目的个数,并且根据解空间限制用户设定的范围(如 range == 2 时,用户却要求生成 10000 道题目,这明显不合理) [ ...
- 四则运算 Java (于泽浩,袁浩越)
GitHub 地址 一. 项目要求 题目 实现一个自动生成小学四则运算题目的命令行程序. 需求(全部完成) 使用 -n 参数控制生成题目的个数 Myapp.exe -n 10 使用 -r 参数控制题目 ...
- Python 实现WC功能
GitHub仓库:https://github.com/15crmor/PAC 项目要求 基本要求 -c 统计文件字符数 (实现) -w 统计文件词数 (实现) -l 统计文件行数(实现) 扩展功能 ...