题意是给你一块在原点半径为10的圆,然后告诉你一条直线在圆弧上的极角,相当于用这条直线把这个圆分成两半,然后一共是n条直线切圆,就好比切蛋糕,问你其中最大一块的面积是多少。

如果我们将圆弧转化成直线边,那么这个题就变成PSLG裸题,但是这里是圆弧,所以我们需要将其转化。

我先将所有在圆上的点记录下来,最后极角排序,绕一周,这些点分割出来肯定会有一部分算面积的时候是要算上那部分弓型面积,但是有一部分不是,主要是这部分面积仅仅就是这块弓型面积,没有其他多边形面积,例如样例3,为了避免这种问题,我们可以直接在相邻两点之间塞入一个点,在进行连边,那么相当于我们给仅仅只有弓型区域内的点一个三角形面积,这样主要保证的是在跑PSLG的时候可以把这块面积算进去,因为每条边只算两次,但是如果是仅仅只有弓型面积所在的那条边,本来应该逆时针绕一圈算面积,所以这样就会有问题。

C++提交正确 G++wa惨???

这样就会有问题

这样建边就没有大问题了

 //      ——By DD_BOND

 //#include<bits/stdc++.h>
//#include<unordered_map>
//#include<unordered_set>
#include<functional>
#include<algorithm>
#include<iostream>
//#include<ext/rope>
#include<iomanip>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<cstddef>
#include<cstdio>
#include<memory>
#include<vector>
#include<cctype>
#include<string>
#include<cmath>
#include<queue>
#include<deque>
#include<ctime>
#include<stack>
#include<map>
#include<set> #define fi first
#define se second
#define pb push_back
#define MP make_pair using namespace std; typedef double db;
typedef long long ll;
typedef pair<db,db> Pd;
typedef pair<int,int> P;
typedef pair<ll,ll> Pll; const db eps=1e-;
const int MAXN=1e5+;
const db pi=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3f; inline int dcmp(db x){
if(fabs(x)<eps) return ;
return (x>? : -);
} inline db Sqrt(db x){
return x>? sqrt(x): ;
} inline db sqr(db x){ return x*x; } struct Point{
db x,y; int id,nx;
Point(){ x=,y=; }
Point(db _x,db _y):x(_x),y(_y){}
void input(){
double _x,_y;
scanf("%lf%lf",&_x,&_y);
x=_x,y=_y;
}
void output(){ printf("%.4f %.4f\n",(double)x,(double)y); }
bool operator ==(const Point &b)const{
return (dcmp(x-b.x)==&&dcmp(y-b.y)==);
}
bool operator !=(const Point &b)const{
return !((dcmp(x-b.x)==&&dcmp(y-b.y)==));
}
bool operator <(const Point &b)const{
return (dcmp(x-b.x)==? dcmp(y-b.y)< : x<b.x);
}
db operator ^(const Point &b)const{ //叉积
return x*b.y-y*b.x;
}
db operator *(const Point &b)const{ //点积
return x*b.x+y*b.y;
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
Point operator *(db a){
return Point(x*a,y*a);
}
Point operator /(db a){
return Point(x/a,y/a);
}
db len2(){ //长度平方
return sqr(x)+sqr(y);
}
db len(){ //长度
return Sqrt(len2());
}
db polar(){ //向量的极角
return atan2(y,x); //返回与x轴正向夹角(-pi~pi]
}
Point rotate_left(){ //逆时针旋转90度
return Point(-y,x);
}
Point rotate_right(){ //顺时针旋转90度
return Point(y,-x);
}
Point rotate(Point p,db ang){ //绕点p逆时针旋转ang度
Point v=(*this)-p;
db c=cos(ang),s=sin(ang);
return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
}
}; inline db cross(Point a,Point b){ //叉积
return a.x*b.y-a.y*b.x;
} inline db dot(Point a,Point b){ //点积
return a.x*b.x+a.y*b.y;
} inline db dis(Point a,Point b){ //两点的距离
Point p=b-a; return p.len();
} inline db rad(Point a,Point b){ //两个向量的夹角
return fabs(atan2(fabs(cross(a,b)),dot(a,b)));
} inline bool is_parallel(Point a,Point b){ //判断向量是否平行
db p=rad(a,b);
return dcmp(p)==||dcmp(p-pi)==;
} struct Line{
Point s,e;
Line(){}
Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
Point operator &(const Line &b)const{ //求两直线交点
Point res=s;
db t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x+=(e.x-s.x)*t;
res.y+=(e.y-s.y)*t;
return res;
}
}; inline int relation(Point p,Line l){ //点和向量关系 1:左侧 2:右侧 3:在线上
int c=dcmp(cross(p-l.s,l.e-l.s));
if(c<) return ;
else if(c>) return ;
else return ;
} inline bool is_parallel(Line a,Line b){ //直线平行
return is_parallel(a.e-a.s,b.e-b.s);
} struct Circle{
Point p;
db r;
Circle(){}
Circle(Point _p,db _r):p(_p),r(_r){}
}; inline int relation(Point p,Circle a){ //点和圆的位置关系 0:圆外 1:圆上 2:圆内
db d=dis(p,a.p);
if(dcmp(d-a.r)==) return ;
return (dcmp(d-a.r)<? : );
} inline db area_radian(db th,db r){ //返回半径为R,弧度为th的弓形面积
return 0.5*r*r*(th-sin(th));
} inline db polygon_area(vector<Point> p){ //多边形的有向面积,加上绝对值就是面积 正值表示输入点按照逆时针 否则为顺时针
int n=p.size(); db area=;
for(int i=;i<n-;i++) area+=cross(p[i]-p[],p[i+]-p[]);
area=fabs(area)/;
for(int i=,j=;i<n;i++,j++){
if(j==n) j=;
if(p[i].nx==p[j].id||p[j].nx==p[i].id) area+=area_radian(rad(p[i],p[j]),);
}
return area;
} struct Edge{
int from,to;
db ang;
Edge(){ ang=from=to=; }
Edge(int s,int t,db a){ from=s,to=t,ang=a; }
};
int n,m,face_cnt; //平面个数 包括外面最大的多边形
db area[MAXN]; //每个多边形面积
Point point[MAXN]; //平面内所有的点
vector<Edge>edge;
vector<int>G[MAXN];
vector<Point>polygon;
vector<Point>face[MAXN];
int vis[*MAXN],pre[*MAXN]; //left表示这条边的左侧属于哪个面
inline void Init(){
for(int i=;i<(int)edge.size();i++) vis[i]=;
edge.clear();
for(int i=;i<n;i++) G[i].clear();
for(int i=;i<face_cnt;i++) face[i].clear();
n=m=face_cnt=;
}
inline void AddEdge(int from, int to){ //需要建立反向边帮助寻找下一条边
edge.pb(Edge(from,to,(point[to]-point[from]).polar()));
edge.pb(Edge(to,from,(point[from]-point[to]).polar()));
m=edge.size();
G[from].pb(m-);
G[to].pb(m-);
}
inline void Build(){
for(int u=;u<n;u++){
int d=G[u].size();
for(int i=;i<d;i++)
for(int j=i+;j<d;j++)
if(edge[G[u][i]].ang>edge[G[u][j]].ang)
swap(G[u][i],G[u][j]);
for(int i=;i<d;i++) pre[G[u][(i+)%d]]=G[u][i]; //从u出发的i条边顺时针旋转的第一条边是pre[i]
}
for(int u=;u<n;u++){
for(int i=;i<(int)G[u].size();i++){
int e=G[u][i];
if(!vis[e]){
while(){
vis[e]=;
int from=edge[e].from;
polygon.pb(point[from]);
e=pre[e^]; //逆时针旋转最多的一条边即为顺时针转动的第一条边
if(e==G[u][i]) break;
}
face[face_cnt++]=polygon;
polygon.clear();
}
}
}
for(int i=;i<face_cnt;i++) area[i]=polygon_area(face[i]);
} typedef pair<Point,int> pdd; pdd st[MAXN];
vector<pair<db,int> >tmp[MAXN]; inline bool cmp(pdd x,pdd y){
return x.fi.polar()<y.fi.polar();
} inline void Insert(Line *line,int m){
for(int i=;i<m;i++)
for(int j=i+;j<m;j++)
if(!is_parallel(line[i],line[j])){
Point inter=line[i]&line[j];
if(dcmp(inter.len()-)>) continue;
point[n++]=inter;
}
sort(point,point+n);
n=unique(point,point+n)-point;
for(int i=;i<n;i++) point[i].id=i;
int cnt=;
for(int i=;i<n;i++)
if(dcmp(point[i].len()-)==)
st[cnt++]=pdd(point[i],i);
sort(st,st+cnt,cmp);
st[cnt]=st[];
for(int i=;i<cnt;i++) st[i].fi.nx=st[i+].fi.id;
for(int i=;i<cnt;i++) point[st[i].se]=st[i].fi;
for(int i=;i<m;i++){
for(int j=;j<n;j++)
if(relation(point[j],line[i])==)
tmp[i].pb(MP(dot(point[j]-line[i].s,line[i].e-line[i].s),j));
sort(tmp[i].begin(),tmp[i].end());
for(int j=;j<(int)tmp[i].size();j++) AddEdge(tmp[i][j-].se,tmp[i][j].se);
}
for(int i=;i<m;i++) tmp[i].clear();
Build();
} typedef pair<db,Point> pd; pd a[MAXN];
Line line[MAXN]; int main(void){
int T; scanf("%d",&T);
while(T--){
Init();
int n,m=,k=; scanf("%d",&n);
for(int i=;i<n;i++){
double x,y; scanf("%lf%lf",&x,&y);
db s=x,t=y;
Point p1=Point(*cos(s),*sin(s));
Point p2=Point(*cos(t),*sin(t));
a[k++]=pd(s,p1);
a[k++]=pd(t,p2);
line[m++]=Line(p1,p2);
}
sort(a,a+k);
k=unique(a,a+k)-a;
a[k]=a[]; a[k].fi+=*pi;
for(int i=;i<k;i++){
Point tmp;
if(dcmp(a[i+].fi-a[i].fi-pi)==) tmp=a[i].se.rotate_left();
else if(dcmp(a[i+].fi-a[i].fi-pi)>){
tmp=a[i].se+a[i+].se;
tmp=tmp/tmp.len()*-;
}
else{
tmp=a[i].se+a[i+].se;
tmp=tmp/tmp.len()*;
}
line[m++]=Line(a[i].se,tmp);
line[m++]=Line(tmp,a[i+].se);
}
Insert(line,m);
sort(area,area+face_cnt);
printf("%.2f\n",(double)area[face_cnt-]);
}
return ;
}

POJ 3743 LL’s cake(圆+PSLG)的更多相关文章

  1. poj 3743 LL’s cake (PSLG,Accepted)

    3743 -- LL’s cake 搞了好久都过不了,看了下题解是用PSLG来做的.POJ 2164 && LA 3218 Find the Border (Geometry, PSL ...

  2. POJ 3675 Telescope 简单多边形和圆的面积交

    这道题得控制好精度,不然会贡献WA  QAQ 还是那个规则: int sgn(double x){ if(x > eps) return 1; else if(x < - eps) ret ...

  3. POJ 3549 GSM phone(圆+扫描线+最短路)

    题目意思是求起点s到终点s的最短路,但是只能在圆的内部和边上走.一种可以想到的方法就是求出所有的交点,然后两两连边并验证合法性,但是这样的交点数规模有n2. 我们可以观察发现,我们在圆求并构成的图形中 ...

  4. POJ 2932 平面扫描 /// 判断圆的包含关系

    题目大意: 平面上有n个两两不相交的圆,给定圆的圆心(x,y)和半径 r 求所有最外层的 即 不包含于其他圆内部的圆 挑战258页 平面扫描 记录所有圆的左端和右端 排序后 逐一扫描 将到当前圆为止的 ...

  5. ACM计算几何题目推荐

    //第一期 计算几何题的特点与做题要领: 1.大部分不会很难,少部分题目思路很巧妙 2.做计算几何题目,模板很重要,模板必须高度可靠. 3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面 ...

  6. 15年-ICPC长春-网络赛

    ID name status one word  POJ 5437 Alisha’s Party 赛后AC. 优先队列,模拟.对时间t排序 POJ 5438 Ponds 赛后AC 循环链表 POJ 5 ...

  7. POJ 2932 圆扫描线

    求n个圆中没有被包含的圆.模仿扫描线从左往右扫,到左边界此时如有3个交点,则有3种情况,以此判定该圆是否被离它最近的圆包含,而交点和最近的圆可以用以y高度排序的Set来维护.因此每次到左边界插入该圆, ...

  8. POJ 2546 &amp; ZOJ 1597 Circular Area(求两圆相交的面积 模板)

    题目链接: POJ:http://poj.org/problem? id=2546 ZOJ:problemId=597" target="_blank">http: ...

  9. 【POJ 1981】Circle and Points(已知圆上两点求圆心坐标)

    [题目链接]:http://poj.org/problem?id=1981 [题意] 给你n个点(n<=300); 然后给你一个半径R: 让你在平面上找一个半径为R的圆; 这里R=1 使得这个圆 ...

随机推荐

  1. 对云信SDK的研究

    1.我首先看了网易的云的各个产品 2.进行了分析发现产品还是很多的 3.主要对web的SDK进行了查看 4.主要有即时通信和聊天室 5.在githup上有网易托管的代码,我用git拉下来,并进行了查看 ...

  2. 从1G到5G发展史(3GPP是个什么组织 为啥5G标准离不开它)

    1.“3GPP”组织建立的来龙去脉 3GPP一直以来在人们心中是一个神秘的组织,很多用户对于它的理解和认知,说不清,道不明.最近关于5G网络的诸多报道,都陈述了“5G网络”的标准是由“3GPP”来规定 ...

  3. Python 爬虫十六式 - 第五式:BeautifulSoup-美味的汤

    BeautifulSoup 美味的汤 学习一时爽,一直学习一直爽!    Hello,大家好,我是Connor,一个从无到有的技术小白.上一次我们说到了 Xpath 的使用方法.Xpath 我觉得还是 ...

  4. idea启动或install时报错:There are test failures,如何跳过测试?

    用idea  install项目时失败,报这样的错: [INFO] BUILD FAILURE [INFO] --------------------------------------------- ...

  5. Python黑科技 | Python中四种运行其他程序的方式

    在Python中,可以方便地使用os模块来运行其他脚本或者程序,这样就可以在脚本中直接使用其他脚本或程序提供的功能,而不必再次编写实现该功能的代码.为了更好地控制运行的进程,可以使用win32proc ...

  6. 程序员心髓:移动应用API设计10大技巧

    移动App与基于Web/云服务发生对话是很常见的事情,最简单的可能仅仅只是检索数据,但也可能包含发送数据.用户授权和管理.而这也就验证了为移动应用建立API的重要性,为此,我们特总结了10大移动API ...

  7. 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果

    let carr = [{ "code": "000", "agyTypeCode": "1", "name& ...

  8. 误用 Kotlin 中的 sortedWith() 方法排序,集合没有变化

    时间:2019年8月4日14:17:06问题描述:看下边的小例子: data class Man(val name: String, val age: Int, val type: Int) fun ...

  9. 高级软件测试技术-任务进度和总结-Day04

    任务进度11-16 使用工具 Jira 小组成员 华同学.郭同学.穆同学.沈同学.覃同学.刘同学 任务进度 经过了这几天的学习和小组成员的努力,虽然其中还准备了考试,但是大家还是最终按时完成了任务,今 ...

  10. Vue 项目构建

    一.初始化项目 1.vue init webpack (fileName) 2.项目名称 3.项目描述 4.项目作者 5.是否依赖 .Vue 文件开发 第一个选项可以不依赖 .Vue 文件开发, 第二 ...