【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] ...
随机推荐
- PTA第五次作业
#include<stdio.h> #include<math.h> int main () { int n,m,i,j,a; scanf("%d",&am ...
- Devexpress VCL Build v2014 vol 14.2.6 发布
终于支持XE8 了.需要这么长时间吗? New Major Features in 14.2 What's New in VCL Products 14.2 Feature Highlights To ...
- 在使用html5的video标签播放视频时为何只有声音却没有图像
在使用html5的video标签播放视频时为何只有声音却没有图像? 答:使用格式化工厂转个编码就行了,MP4有3种编码,mpg4(xdiv),,mpg4(xvid),avc(h264)转换成H264编 ...
- 2018.06.29 NOIP模拟 Minimum(最小生成树)
Minimum 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一幅由 n 个点 m 条边构成的无向带权图. 其中有些点是黑点,另外点是白点. 现在每个白点都要与他距离最近的所有黑 ...
- js动态添加删除行,兼容ie和火狐
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- UVa 10382 Watering Grass (区间覆盖贪心问题+数学)
题意:有一块长为l,宽为w的草地,在其中心线有n个喷水装置,每个装置可喷出以p为中心以r为半径的圆, 选择尽量少的装置,把草地全部润湿. 析:我个去啊,做的真恶心,看起来很简单,实际上有n多个坑啊,首 ...
- web.xml 404 500 配置
web.xml <error-page> <error-code>404</error-code> <location>/error404.html&l ...
- Object-C中方法
//方法 //方法分了两种 //1.类方法,类调用,方法以+开头 //2.实例方法,对象调用,方法以-开头 //类方法和实例方 ...
- windows7,windows8 64位系统 IIS7.0配置.net网站时报错:未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。
背景: 在64位的操作系统中, IIS7.0配置.net网站时报错:未能加载文件或程序集“XXX”或它的某一个依赖项.试图加载格式不正确的程序. 解决办法: 把iis 对应的应用程序池 --高级设置- ...
- LeetCode135:Candy
题目: There are N children standing in a line. Each child is assigned a rating value. You are giving c ...