POJ 3743 LL’s cake(圆+PSLG)

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

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

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

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

这样就会有问题

这样建边就没有大问题了

  1 //      ——By DD_BOND
  2
  3 //#include<bits/stdc++.h>
  4 //#include<unordered_map>
  5 //#include<unordered_set>
  6 #include<functional>
  7 #include<algorithm>
  8 #include<iostream>
  9 //#include<ext/rope>
 10 #include<iomanip>
 11 #include<climits>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<cstddef>
 15 #include<cstdio>
 16 #include<memory>
 17 #include<vector>
 18 #include<cctype>
 19 #include<string>
 20 #include<cmath>
 21 #include<queue>
 22 #include<deque>
 23 #include<ctime>
 24 #include<stack>
 25 #include<map>
 26 #include<set>
 27
 28 #define fi first
 29 #define se second
 30 #define pb push_back
 31 #define MP make_pair
 32
 33 using namespace std;
 34
 35 typedef double db;
 36 typedef long long ll;
 37 typedef pair<db,db> Pd;
 38 typedef pair<int,int> P;
 39 typedef pair<ll,ll> Pll;
 40
 41 const db eps=1e-8;
 42 const int MAXN=1e5+10;
 43 const db pi=acos(-1.0);
 44 const ll INF=0x3f3f3f3f3f3f3f3f;
 45
 46 inline int dcmp(db x){
 47     if(fabs(x)<eps) return 0;
 48     return (x>0? 1: -1);
 49 }
 50
 51 inline db Sqrt(db x){
 52     return x>0? sqrt(x): 0;
 53 }
 54
 55 inline db sqr(db x){ return x*x; }
 56
 57 struct Point{
 58     db x,y; int id,nx;
 59     Point(){ x=0,y=0; }
 60     Point(db _x,db _y):x(_x),y(_y){}
 61     void input(){
 62         double _x,_y;
 63         scanf("%lf%lf",&_x,&_y);
 64         x=_x,y=_y;
 65     }
 66     void output(){ printf("%.4f %.4f\n",(double)x,(double)y); }
 67     bool operator ==(const Point &b)const{
 68         return (dcmp(x-b.x)==0&&dcmp(y-b.y)==0);
 69     }
 70     bool operator !=(const Point &b)const{
 71         return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0));
 72     }
 73     bool operator <(const Point &b)const{
 74         return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x);
 75     }
 76     db operator ^(const Point &b)const{     //叉积
 77         return x*b.y-y*b.x;
 78     }
 79     db operator *(const Point &b)const{     //点积
 80         return x*b.x+y*b.y;
 81     }
 82     Point operator +(const Point &b)const{
 83         return Point(x+b.x,y+b.y);
 84     }
 85     Point operator -(const Point &b)const{
 86         return Point(x-b.x,y-b.y);
 87     }
 88     Point operator *(db a){
 89         return Point(x*a,y*a);
 90     }
 91     Point operator /(db a){
 92         return Point(x/a,y/a);
 93     }
 94     db len2(){  //长度平方
 95         return sqr(x)+sqr(y);
 96     }
 97     db len(){   //长度
 98         return Sqrt(len2());
 99     }
100     db polar(){ //向量的极角
101         return atan2(y,x);   //返回与x轴正向夹角(-pi~pi]
102     }
103     Point rotate_left(){    //逆时针旋转90度
104         return Point(-y,x);
105     }
106     Point rotate_right(){   //顺时针旋转90度
107         return Point(y,-x);
108     }
109     Point rotate(Point p,db ang){   //绕点p逆时针旋转ang度
110         Point v=(*this)-p;
111         db c=cos(ang),s=sin(ang);
112         return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
113     }
114 };
115
116 inline db cross(Point a,Point b){   //叉积
117     return a.x*b.y-a.y*b.x;
118 }
119
120 inline db dot(Point a,Point b){ //点积
121     return a.x*b.x+a.y*b.y;
122 }
123
124 inline db dis(Point a,Point b){ //两点的距离
125     Point p=b-a;    return p.len();
126 }
127
128 inline db rad(Point a,Point b){    //两个向量的夹角
129     return fabs(atan2(fabs(cross(a,b)),dot(a,b)));
130 }
131
132 inline bool is_parallel(Point a,Point b){  //判断向量是否平行
133     db p=rad(a,b);
134     return dcmp(p)==0||dcmp(p-pi)==0;
135 }
136
137 struct Line{
138     Point s,e;
139     Line(){}
140     Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
141     Point operator &(const Line &b)const{    //求两直线交点
142         Point res=s;
143         db t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
144         res.x+=(e.x-s.x)*t;
145         res.y+=(e.y-s.y)*t;
146         return res;
147     }
148 };
149
150 inline int relation(Point p,Line l){   //点和向量关系   1:左侧   2:右侧   3:在线上
151     int c=dcmp(cross(p-l.s,l.e-l.s));
152     if(c<0) return 1;
153     else if(c>0)    return 2;
154     else    return 3;
155 }
156
157 inline bool is_parallel(Line a,Line b){    //直线平行
158     return is_parallel(a.e-a.s,b.e-b.s);
159 }
160
161 struct Circle{
162     Point p;
163     db r;
164     Circle(){}
165     Circle(Point _p,db _r):p(_p),r(_r){}
166 };
167
168 inline int relation(Point p,Circle a){ //点和圆的位置关系  0:圆外    1:圆上   2:圆内
169     db d=dis(p,a.p);
170     if(dcmp(d-a.r)==0)  return 1;
171     return (dcmp(d-a.r)<0? 2: 0);
172 }
173
174 inline db area_radian(db th,db r){ //返回半径为R,弧度为th的弓形面积
175     return 0.5*r*r*(th-sin(th));
176 }
177
178 inline db polygon_area(vector<Point> p){    //多边形的有向面积,加上绝对值就是面积  正值表示输入点按照逆时针 否则为顺时针
179     int n=p.size(); db area=0;
180     for(int i=1;i<n-1;i++)  area+=cross(p[i]-p[0],p[i+1]-p[0]);
181     area=fabs(area)/2;
182     for(int i=0,j=1;i<n;i++,j++){
183         if(j==n)    j=0;
184         if(p[i].nx==p[j].id||p[j].nx==p[i].id)  area+=area_radian(rad(p[i],p[j]),10);
185     }
186     return area;
187 }
188
189 struct Edge{
190     int from,to;
191     db ang;
192     Edge(){ ang=from=to=0; }
193     Edge(int s,int t,db a){ from=s,to=t,ang=a; }
194 };
195 int n,m,face_cnt;   //平面个数 包括外面最大的多边形
196 db area[MAXN];  //每个多边形面积
197 Point point[MAXN];  //平面内所有的点
198 vector<Edge>edge;
199 vector<int>G[MAXN];
200 vector<Point>polygon;
201 vector<Point>face[MAXN];
202 int vis[2*MAXN],pre[2*MAXN];   //left表示这条边的左侧属于哪个面
203 inline void Init(){
204     for(int i=0;i<(int)edge.size();i++)  vis[i]=0;
205     edge.clear();
206     for(int i=0;i<n;i++)    G[i].clear();
207     for(int i=0;i<face_cnt;i++) face[i].clear();
208     n=m=face_cnt=0;
209 }
210 inline void AddEdge(int from, int to){             //需要建立反向边帮助寻找下一条边
211     edge.pb(Edge(from,to,(point[to]-point[from]).polar()));
212     edge.pb(Edge(to,from,(point[from]-point[to]).polar()));
213     m=edge.size();
214     G[from].pb(m-2);
215     G[to].pb(m-1);
216 }
217 inline void Build(){
218     for(int u=0;u<n;u++){
219         int d=G[u].size();
220         for(int i=0;i<d;i++)
221             for(int j=i+1;j<d;j++)
222                 if(edge[G[u][i]].ang>edge[G[u][j]].ang)
223                     swap(G[u][i],G[u][j]);
224         for(int i=0;i<d;i++)    pre[G[u][(i+1)%d]]=G[u][i]; //从u出发的i条边顺时针旋转的第一条边是pre[i]
225     }
226     for(int u=0;u<n;u++){
227         for(int i=0;i<(int)G[u].size();i++){
228             int e=G[u][i];
229             if(!vis[e]){
230                 while(1){
231                     vis[e]=1;
232                     int from=edge[e].from;
233                     polygon.pb(point[from]);
234                     e=pre[e^1];         //逆时针旋转最多的一条边即为顺时针转动的第一条边
235                     if(e==G[u][i])  break;
236                 }
237                 face[face_cnt++]=polygon;
238                 polygon.clear();
239            }
240         }
241     }
242     for(int i=0;i<face_cnt;i++)  area[i]=polygon_area(face[i]);
243 }
244
245 typedef pair<Point,int> pdd;
246
247 pdd st[MAXN];
248 vector<pair<db,int> >tmp[MAXN];
249
250 inline bool cmp(pdd x,pdd y){
251     return x.fi.polar()<y.fi.polar();
252 }
253
254 inline void Insert(Line *line,int m){
255     for(int i=0;i<m;i++)
256         for(int j=i+1;j<m;j++)
257             if(!is_parallel(line[i],line[j])){
258                 Point inter=line[i]&line[j];
259                 if(dcmp(inter.len()-10)>0)  continue;
260                 point[n++]=inter;
261             }
262     sort(point,point+n);
263     n=unique(point,point+n)-point;
264     for(int i=0;i<n;i++)    point[i].id=i;
265     int cnt=0;
266     for(int i=0;i<n;i++)
267         if(dcmp(point[i].len()-10)==0)
268             st[cnt++]=pdd(point[i],i);
269     sort(st,st+cnt,cmp);
270     st[cnt]=st[0];
271     for(int i=0;i<cnt;i++)   st[i].fi.nx=st[i+1].fi.id;
272     for(int i=0;i<cnt;i++)   point[st[i].se]=st[i].fi;
273     for(int i=0;i<m;i++){
274         for(int j=0;j<n;j++)
275             if(relation(point[j],line[i])==3)
276                 tmp[i].pb(MP(dot(point[j]-line[i].s,line[i].e-line[i].s),j));
277         sort(tmp[i].begin(),tmp[i].end());
278         for(int j=1;j<(int)tmp[i].size();j++)  AddEdge(tmp[i][j-1].se,tmp[i][j].se);
279     }
280     for(int i=0;i<m;i++)    tmp[i].clear();
281     Build();
282 }
283
284 typedef pair<db,Point> pd;
285
286 pd a[MAXN];
287 Line line[MAXN];
288
289 int main(void){
290     int T;  scanf("%d",&T);
291     while(T--){
292         Init();
293         int n,m=0,k=0;  scanf("%d",&n);
294         for(int i=0;i<n;i++){
295             double x,y; scanf("%lf%lf",&x,&y);
296             db s=x,t=y;
297             Point p1=Point(10*cos(s),10*sin(s));
298             Point p2=Point(10*cos(t),10*sin(t));
299             a[k++]=pd(s,p1);
300             a[k++]=pd(t,p2);
301             line[m++]=Line(p1,p2);
302         }
303         sort(a,a+k);
304         k=unique(a,a+k)-a;
305         a[k]=a[0];  a[k].fi+=2*pi;
306         for(int i=0;i<k;i++){
307             Point tmp;
308             if(dcmp(a[i+1].fi-a[i].fi-pi)==0)   tmp=a[i].se.rotate_left();
309             else if(dcmp(a[i+1].fi-a[i].fi-pi)>0){
310                 tmp=a[i].se+a[i+1].se;
311                 tmp=tmp/tmp.len()*-10;
312             }
313             else{
314                 tmp=a[i].se+a[i+1].se;
315                 tmp=tmp/tmp.len()*10;
316             }
317             line[m++]=Line(a[i].se,tmp);
318             line[m++]=Line(tmp,a[i+1].se);
319         }
320         Insert(line,m);
321         sort(area,area+face_cnt);
322         printf("%.2f\n",(double)area[face_cnt-2]);
323     }
324     return 0;
325 }

原文地址:https://www.cnblogs.com/dd-bond/p/11622309.html

时间: 2024-11-07 09:18:30

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

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

这道题得控制好精度,不然会贡献WA  QAQ 还是那个规则: int sgn(double x){ if(x > eps) return 1; else if(x < - eps) return -1; else return 0; } 思路:把简单多边形的每一个点和原点连线,就把这个多边形和圆的交变成了多个三角形与圆的交,根据有向面积的思路,加加减减就可以得到公共面积. 贴上代码了- #include <cstdio> #include <cstring> #incl

A Round Peg in a Ground Hole POJ - 1584(凸边形与圆相交)

A Round Peg in a Ground Hole POJ - 1584 题目链接:https://vjudge.net/problem/POJ-1584#author=0 题意:要求钉子要钉入孔内,判断能否在指定点钉入 思路:先判断这些点围成的多边形是不是凸多边形,如果是那么判断圆是否在凸边形里,若在那么就输出“PEG WILL FIT“,不在凸边形里就输出“PEG WILL NOT FIT”,如果都不是凸边形那么输出“HOLE IS ILL-FORMED” // // Created

POJ 1375 Intervals 解析几何 求圆的切线

题目大意:给出一个点,再给出都处于这个点之下的一些圆,求这个点光源照到这些圆上之后所得到的阴影的并集. 思路:求出每一个圆关于那个点的切线,每一个圆可以处理出来两个切线,这两个切线在x轴上交点的中间部分就是要求的阴影.最后将所有的阴影部分取并输出. 关于求切线,我是利用方向向量解方程做的.应该有更简洁的方法吧.. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostre

poj 3587 The Biggest Cake 正弦定理

题意: 给n个点,求其中3个点构成三角形的最大外接圆半径. 分析: 正弦定理,A/sina=B/sinb=C/sinc=ABC/(2*s)=2*R. 代码: //poj 3587 //sep9 #include <iostream> #include <cmath> using namespace std; const int maxN=700; double dis[maxN][maxN]; double x[maxN],y[maxN]; double cross(double

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

题目意思是求起点s到终点s的最短路,但是只能在圆的内部和边上走.一种可以想到的方法就是求出所有的交点,然后两两连边并验证合法性,但是这样的交点数规模有n2. 我们可以观察发现,我们在圆求并构成的图形中,在其内部的点是不可能成为最短路上的点,只可能是沿着边上的点擦着经过,所以我们需要把在圆内部的所有点都给扣掉,同样可以证明这样的点的规模只有n个,接下来只需要暴力连边,但是连边的时候需要验证这样的点对是否沿着直线可达.我是直接将这条线段暴力和所有圆求交点,左侧端点计为1,右侧端点计为-1,然后用类似

【转】[专题学习][计算几何]

原文地址:http://www.cnblogs.com/ch3656468/archive/2011/03/02/1969303.html 基本的叉积.点积和凸包等东西就不多说什么了,网上一搜一大堆,切一些题目基本熟悉了就差不多了. 一些基本的题目可以自己搜索,比如这个blog:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 接下来,研究了半平面交,思想方法看07年朱泽园的国家队论文,模板代码参考自我校大牛韬哥: http://www.o

计算几何题目分类

转载 一.基础题目 1.1 有固定算法的题目 A, 最近点对问题最近点对问题的算法基于扫描线算法.ZOJ 2107    Quoit Design    典型最近点对问题POJ    3714    Raid    变种最近点对问题 B,最小包围圆最小包围圆的算法是一种增量算法,期望是O(n).ZOJ    1450    Minimal Circle  HDU    3007    Buried memory C,旋转卡壳POJ 3608    Bridge Across Islands   

15年-ICPC长春-网络赛

ID name status one word    POJ 5437 Alisha’s Party 赛后AC. 优先队列,模拟.对时间t排序 #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> using namespace std; struct Node { char name[210]; int v

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

题目链接: POJ:http://poj.org/problem?id=2546 ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=597 Description Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three di