17.8.19 校内赛 解题报告【求线段交点+凸包+求多边形面积】【判定点是否在多边形内】【二分答案+半平面交】
来源:互联网 发布:p2p网络终结者手机版 编辑:程序博客网 时间:2024/05/16 14:18
Problem 1. land
解题报告
显然,这道题就是线段求交点+凸包+求多边形面积
问题就是我们只有直线求交点的模板和判线段相交的模板,没有直接求线段相交的。我是这样解决的:先判断两线段是否相交,然后再把线段存储为直线,求出两者的交点。
代码如下:
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define Point Vector#define NAME "land"using namespace std;const double eps=1e-8;const int N=1000;int sign(double a){return a>eps?1:(a<-eps?-1:0);}struct Vector{ double x,y; double len(){return sqrt(x*x+y*y);} double ang(){return atan2(y,x);} Vector(double a=.0,double b=.0):x(a),y(b){} Vector operator+(const Vector &s){return Vector(x+s.x,y+s.y);} Vector operator-(const Vector &s){return Vector(x-s.x,y-s.y);} Vector operator*(double s){return Vector(x*s,y*s);} Vector operator/(double s){return Vector(x/s,y/s);}};struct Seg{ Point A,B; Seg(){} Seg(Point a,Point b):A(a),B(b){}}Segs[N+5];struct Line{ Point p; Vector u; double ang; Line(){} Line(Point p,Vector v):p(p),u(v),ang(u.ang()){} bool operator<(const Line &s){return ang<s.ang;} bool operator==(const Line &s){return sign(ang-s.ang)==0;}};bool cmp(Point r,Point s){ if(r.x==s.x)return r.y<s.y; return r.x<s.x;}double dot(const Vector &a,const Vector &b){return a.x*b.x+a.y*b.y;}//向量点积 double cross(const Vector &a,const Vector &b){return a.x*b.y-a.y*b.x;}//向量叉积bool onleft(Point a,Point b,Point p){ return sign(cross(b-a,p-a))>0;}bool onleft(Line l,Point p){ return sign(cross(l.u,p-l.p))>0;}vector<Point>convex(vector<Point>pts)//求凸包 { int n=(int)pts.size(),m=0; vector<Point>cvx; sort(pts.begin(),pts.end(),cmp); for(int i=0;i<n;i++) { while(m>1&&onleft(cvx[m-2],cvx[m-1],pts[i])){cvx.pop_back();m--;} cvx.push_back(pts[i]);m++; } int k=m; for(int i=n-2;i>=0;i--) { while(m>k&&onleft(cvx[m-2],cvx[m-1],pts[i])){cvx.pop_back();m--;} cvx.push_back(pts[i]);m++; } if(n>1){m--;cvx.pop_back();} return cvx;}double area(vector<Point>poly)//求多边形的面积 { double rt=0.0; int n=(int)poly.size(); for(int i=0;i<n;i++)rt+=cross(poly[i],poly[(i+1)%n]); return fabs(rt/2.0);}Point line_intersect(Point P,Vector u,Point Q,Vector v) { double t=cross(Q-P,v)/cross(u,v); return P+u*t;}Point line_intersect(const Line &a,const Line &b)//求出两直线交点 { return line_intersect(a.p,a.u,b.p,b.u);}bool seg_intersect(Point A,Point B,Point C,Point D)//判定两线段(AB,CD)是否相交 { double c1=cross(B-A,C-A),c2=cross(B-A,D-A); double c3=cross(D-C,A-C),c4=cross(D-C,B-C); return sign(c1)*sign(c2)<0&&sign(c3)*sign(c4)<0;}int n;vector<Point>pts,poly; int main(){ freopen(NAME".in","r",stdin); freopen(NAME".out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); Segs[i]=Seg(Point(x1,y1),Point(x2,y2)); } for(int i=1;i<=n-1;i++) for(int j=i+1;j<=n;j++) { if(seg_intersect(Segs[i].A,Segs[i].B,Segs[j].A,Segs[j].B)) pts.push_back(line_intersect(Line((Segs[i].A),Segs[i].B-Segs[i].A),Line((Segs[j].A),Segs[j].B-Segs[j].A))); } poly=convex(pts); double ans=area(poly); printf("%.2lf",ans); return 0;}
Problem 2. escape
解题报告
直接套模板上:
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define Point Vector#define NAME "escape"using namespace std;const double eps=1e-8;int sign(double a){return a>eps?1:(a<-eps?-1:0);}struct Vector{ double x,y; double len(){return sqrt(x*x+y*y);} double ang(){return atan2(y,x);} Vector(double a=.0,double b=.0):x(a),y(b){} Vector operator+(const Vector &s){return Vector(x+s.x,y+s.y);} Vector operator-(const Vector &s){return Vector(x-s.x,y-s.y);} Vector operator*(double s){return Vector(x*s,y*s);} Vector operator/(double s){return Vector(x/s,y/s);}};double dot(const Vector &a,const Vector &b){return a.x*b.x+a.y*b.y;}//向量点积 double cross(const Vector &a,const Vector &b){return a.x*b.y-a.y*b.x;}//向量叉积bool point_on_line(Point p,Point A,Point B)//判定点是否在线段上 { return sign(cross(B-A,p-A))==0&&sign(dot(A-p,B-p))<=0;}bool in_polygon(Point p,vector<Point>poly)//判定点是否在多边形内 { int n=(int)poly.size(); int counter=0; for(int i=0;i<n;++i) { Point a=poly[i],b=poly[(i+1)%n]; if(point_on_line(p,a,b))return true; // bounded included int x=sign(cross(p-a,b-a)); int y=sign(a.y-p.y); int z=sign(b.y-p.y); if(x>0&&y<=0&&z>0)counter++; if(x<0&&z<=0&&y>0)counter--; } return counter!=0;}int n,q;vector<Point>poly;int main(){ freopen(NAME".in","r",stdin); freopen(NAME".out","w",stdout); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { double x,y; scanf("%lf%lf",&x,&y); poly.push_back(Point(x,y)); } while(q--) { double x,y; scanf("%lf%lf",&x,&y); if(in_polygon(Point(x,y),poly))printf("YES\n"); else printf("NO\n"); } return 0;}
Problem 3. island
解题报告
这是蓝书上的例题,可以看我的这篇博客
代码如下:
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define NAME "island"#define Point Vectorusing namespace std;const double eps=1e-8;const int N=1e5;int sign(double a){return a>eps?1:(a<-eps?-1:0);}struct Vector{ double x,y; double len(){return sqrt(x*x+y*y);} double ang(){return atan2(y,x);} Vector(double a=.0,double b=.0):x(a),y(b){} Vector operator+(const Vector &s){return Vector(x+s.x,y+s.y);} Vector operator-(const Vector &s){return Vector(x-s.x,y-s.y);} Vector operator*(double s){return Vector(x*s,y*s);} Vector operator/(double s){return Vector(x/s,y/s);}};Vector Normal(Vector a){double L=a.len();return Vector(-a.y/L,a.x/L);}struct Line{ Point p; Vector u; double ang; Line(){} Line(Point p,Vector v):p(p),u(v),ang(u.ang()){} bool operator<(const Line &s){return ang<s.ang;} bool operator==(const Line &s){return sign(ang-s.ang)==0;} bool operator<(const Line&L)const{return ang<L.ang;}};double dot(const Vector &a,const Vector &b){return a.x*b.x+a.y*b.y;}//向量点积 double cross(const Vector &a,const Vector &b){return a.x*b.y-a.y*b.x;}//向量叉积Point line_intersect(Point P,Vector u,Point Q,Vector v) { double t=cross(Q-P,v)/cross(u,v); return P+u*t;}Point line_intersect(const Line &a,const Line &b)//求出两直线交点 { return line_intersect(a.p,a.u,b.p,b.u);}bool seg_intersect(Point A,Point B,Point C,Point D)//判定两线段(AB,CD)是否相交 { double c1=cross(B-A,C-A),c2=cross(B-A,D-A); double c3=cross(D-C,A-C),c4=cross(D-C,B-C); return sign(c1)*sign(c2)<0&&sign(c3)*sign(c4)<0;}bool cmp1(Line r,Line s){ return r<s;}bool onleft(Point a,Point b,Point p){ return sign(cross(b-a,p-a))>0;}bool onleft(Line l,Point p){ return sign(cross(l.u,p-l.p))>0;}vector<Point>half_plane_intersect(vector<Line>L){ int n=L.size(); sort(L.begin(),L.end()); int first,last; vector<Point> p(n); vector<Line> q(n); vector<Point> ans; q[first=last=0]=L[0]; for(int i=1;i<n;i++) { while(first<last&&!onleft(L[i],p[last-1]))last--; while(first<last&&!onleft(L[i],p[first]))first++; q[++last]=L[i]; if(fabs(cross(q[last].u,q[last-1].u))<eps) { last--; if(onleft(q[last],L[i].p))q[last]=L[i]; } if(first<last)p[last-1]=line_intersect(q[last-1],q[last]); } while(first<last&&!onleft(q[first],p[last-1]))last--; if(last-first<=1)return ans; p[last]=line_intersect(q[last],q[first]); for(int i=first;i<=last;i++)ans.push_back(p[i]); return ans;}int n;int main(){ freopen(NAME".in","r",stdin); freopen(NAME".out","w",stdout); scanf("%d",&n); vector<Point>p,v,normal; for(int i=1;i<=n;i++) { double x,y; scanf("%lf%lf",&x,&y); p.push_back(Point(x,y)); } for(int i=0;i<=n-1;i++) { v.push_back(p[(i+1)%n]-p[i]); normal.push_back(Normal(v[i])); } double lf=0,rg=20000; while(rg-lf>eps) { vector<Line>h; double mid=lf+(rg-lf)/2.0; for(int i=0;i<=n-1;i++) h.push_back(Line(p[i]+normal[i]*mid,v[i])); vector<Point>poly=half_plane_intersect(h); if(poly.empty())rg=mid; else lf=mid; } printf("%.2lf",lf); return 0;}
阅读全文
1 0
- 17.8.19 校内赛 解题报告【求线段交点+凸包+求多边形面积】【判定点是否在多边形内】【二分答案+半平面交】
- POJ 3384 Feng Shui (半平面交求多边形内两个圆最大面积)
- 【PKU3525】半平面交二分求多边形核
- scu1778求多边形交面积
- ecnu1624求交集多边形面积 (凸多边形交——半平面交)
- (beginer)线段求交:多边形面积 UVA 1301 - Fishnet
- 怎么求一个点是否在一个多边形内呢?
- poj 1279 Art Gallery(求多边形核的面积+半平面交)
- poj 1279 Art Gallery(半平面交求多边形核面积)
- POJ 1279 Art Gallery 半平面交+求多边形核的面积
- POJ-1279 Art Gallery(求多边形内核面积,半平面交)
- POJ 3525 二分答案,推进多边形和半平面交
- POJ 3525 二分答案,推进多边形和半平面交
- HDU1154求线段在多边形内长度
- POJ3348Cows【凸包+多边形求面积】
- 点在多边形内判定
- hdu1154(点是否在多边形内部、两线段交点)
- 求圆和多边形的面积交
- C++空间分配器简述学习笔记
- sublime快捷键实现自动push
- Luogu P1314 [NOIp提高组2011]聪明的质监员
- C++语言对有理数的封装Rational
- Xshell连接虚拟机
- 17.8.19 校内赛 解题报告【求线段交点+凸包+求多边形面积】【判定点是否在多边形内】【二分答案+半平面交】
- apache2.4配置域名后,访问域名出现apache欢迎页
- PID学习实录
- python入门(二十九):面向对象之多态
- 2017 ccpc网络预选赛 CaoHaha's staff
- PYTHON爬虫学习
- JavaScript—字符串
- xutils3使用方法
- HDU 6138 Fleet of the Eternal Throne 后缀数组+字典树