POJ 3743 LL’s cake(圆+PSLG)
题意是给你一块在原点半径为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)的更多相关文章
- poj 3743 LL’s cake (PSLG,Accepted)
3743 -- LL’s cake 搞了好久都过不了,看了下题解是用PSLG来做的.POJ 2164 && LA 3218 Find the Border (Geometry, PSL ...
- POJ 3675 Telescope 简单多边形和圆的面积交
这道题得控制好精度,不然会贡献WA QAQ 还是那个规则: int sgn(double x){ if(x > eps) return 1; else if(x < - eps) ret ...
- POJ 3549 GSM phone(圆+扫描线+最短路)
题目意思是求起点s到终点s的最短路,但是只能在圆的内部和边上走.一种可以想到的方法就是求出所有的交点,然后两两连边并验证合法性,但是这样的交点数规模有n2. 我们可以观察发现,我们在圆求并构成的图形中 ...
- POJ 2932 平面扫描 /// 判断圆的包含关系
题目大意: 平面上有n个两两不相交的圆,给定圆的圆心(x,y)和半径 r 求所有最外层的 即 不包含于其他圆内部的圆 挑战258页 平面扫描 记录所有圆的左端和右端 排序后 逐一扫描 将到当前圆为止的 ...
- ACM计算几何题目推荐
//第一期 计算几何题的特点与做题要领: 1.大部分不会很难,少部分题目思路很巧妙 2.做计算几何题目,模板很重要,模板必须高度可靠. 3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面 ...
- 15年-ICPC长春-网络赛
ID name status one word POJ 5437 Alisha’s Party 赛后AC. 优先队列,模拟.对时间t排序 POJ 5438 Ponds 赛后AC 循环链表 POJ 5 ...
- POJ 2932 圆扫描线
求n个圆中没有被包含的圆.模仿扫描线从左往右扫,到左边界此时如有3个交点,则有3种情况,以此判定该圆是否被离它最近的圆包含,而交点和最近的圆可以用以y高度排序的Set来维护.因此每次到左边界插入该圆, ...
- POJ 2546 & ZOJ 1597 Circular Area(求两圆相交的面积 模板)
题目链接: POJ:http://poj.org/problem? id=2546 ZOJ:problemId=597" target="_blank">http: ...
- 【POJ 1981】Circle and Points(已知圆上两点求圆心坐标)
[题目链接]:http://poj.org/problem?id=1981 [题意] 给你n个点(n<=300); 然后给你一个半径R: 让你在平面上找一个半径为R的圆; 这里R=1 使得这个圆 ...
随机推荐
- VUE实现限制输入框最多输入15个中文,或者30个英文
vue项目,输入框限制输入15个中文,或者30个英文 <input type="text" v-model="groupName" class=" ...
- Apache Flink CEP 实战
本文根据Apache Flink 实战&进阶篇系列直播课程整理而成,由哈啰出行大数据实时平台资深开发刘博分享.通过一些简单的实际例子,从概念原理,到如何使用,再到功能的扩展,希望能够给打算使用 ...
- IDC装机检查思路
交换机网口 网线 配线架 服务器网口灯 系统网卡驱动
- 记录下:nth-child在table中遇到的问题~(已解决)
首先做了一个表格,如下: <!DOCTYPE html> <html> <head> <title></title> <style t ...
- vue学习-day02(自定义指令,生命周期)
目录: 1.案例:品牌管理 2.Vue-devtools的两种安装方式 3.过滤器,自定义全局或私有过滤器 4.鼠标按键事件的修饰符 5.自定义全局指令:让文本框获取焦点 ...
- XML 浏览器支持
几乎所有的主流浏览器均支持 XML 和 XSLT. Mozilla Firefox 从 1.0.2 版本开始,Firefox 就已开始支持 XML 和 XSLT(包括 CSS). Mozilla Mo ...
- 浅谈Vue中Slot以及slot-scope
vue中关于插槽的文档说明很短,语言又写的很凝练,再加上其和methods,data,computed等常用选项使用频率.使用先后上的差别,这就有可能造成初次接触插槽的开发者容易产生“算了吧,回头再学 ...
- 模板_BIT
#include<bits/stdc++.h> #define maxn 500005 //#define int long long using namespace std; inlin ...
- zookeeper3.5.5集群部署
ZooKeeper是一个为分布式应用所设计的分布的.开源的协调服务,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,简化分布式应用协调及其管理的难度,提供高性能的分布式服务.ZooKeeper ...
- python3.7--pycharm selenium自启360浏览器/360极速浏览器方法
写于:2019.01.02(实测日) 参考文档:https://blog.csdn.net/five3/article/details/50013159 一.下载360浏览器或360极速浏览器的Chr ...