计算几何模板 (bzoj 1336,poj 2451 ,poj3968)
poj 3968 (bzoj 2642)
二分+半平面交,每次不用排序,这是几个算几版综合。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<deque> using namespace std; #define MAXN 100000 namespace geometry { typedef long double real; const real pi=3.1415926535897; const real eps=1e-8; inline real sqr(real x) { return x*x; } inline int sgn(real x) { if (abs(x)<eps)return 0; return x<0?-1:1; } class point { public: real x,y; point(){x=y=0;} point(real x,real y):x(x),y(y){}; void read(); void print(); }; inline void point::read() { double xx,yy; scanf("%lf%lf\n",&xx,&yy); x=xx;y=yy; } inline void point::print() { printf("Point:[%.2lf,%.2lf]\n",(double)x,(double)y); } inline real dis(point p1,point p2) { return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y)); } inline bool cmp_point_position(point p1,point p2) { if (p1.y!=p2.y)return p1.y<p2.y; return p1.x<p2.x; } class line { public: point ps; point pt; line(){} line(point ps,point pt):ps(ps),pt(pt){} line(point ps,real dx,real dy); real len(); real angle(); bool leftside(point pp); bool rightside(point pp); void print(); point mid_point(); line mid_vertical(); }; inline real dot(line& l1,line& l2) { return (l1.pt.x-l1.ps.x)*(l2.pt.x-l2.ps.x) +(l1.pt.y-l1.ps.y)*(l2.pt.y-l2.ps.y); } inline real det(line l1,line l2) { return (l1.pt.x-l1.ps.x)*(l2.pt.y-l2.ps.y) - (l1.pt.y-l1.ps.y)*(l2.pt.x-l2.ps.x); } line::line(point ps,real dx,real dy) { this->ps=ps; this->pt.x=ps.x+dx; this->pt.y=ps.y+dy; } inline real line::len() { return sqrt(sqr(pt.x-ps.x)+sqr(pt.y-ps.y)); } inline real line::angle() { return atan2(pt.x-ps.x,pt.y-ps.y); //if (pt.y>=ps.y) // return -(pt.x-ps.x)/len(); //else // return (pt.x-ps.x)/len()+10; //if (pt.y>=ps.y) // return acos((pt.x-ps.x)/len()); //else // return 2*pi-acos((pt.x-ps.x)/len()); } inline bool line::leftside(point pp) { return sgn(det(line(pp,ps),*this))>0; } inline bool line::rightside(point pp) { return sgn(det(line(pp,ps),*this))<0; } inline void line::print() { printf("Line:[%.2lf,%.2lf] -> [%.2lf,%.2lf]\n",(double)ps.x,(double)ps.y,(double)pt.x,(double)pt.y); } point line::mid_point() { return point((ps.x+pt.x)/2,(ps.y+pt.y)/2); } line line::mid_vertical() { return line(mid_point(),pt.y-ps.y,ps.x-pt.x); } inline real operator *(line l1,line l2) { return det(l1,l2); } inline line operator -(point p1,point p2) { return line(p2,p1); } inline bool parallel(line l1,line l2) { //return sgn(l1.angle()-l2.angle())==0; return sgn(det(l1,l2))==0; } inline point crossover(line l1,line l2) { if (!sgn(det(l1,l2)))throw 1; real s1=det(l1,l2.ps-l1.ps); real s2=-det(l1,l2.pt-l1.ps); return point(l2.ps.x+s1/(s1+s2)*(l2.pt.x-l2.ps.x), l2.ps.y+s1/(s1+s2)*(l2.pt.y-l2.ps.y)); } inline real area(point p1,point p2,point p3) { return det(line(p2,p1),line(p3,p1))/2; } typedef line halfplane; inline bool cmp_line_angle(line l1,line l2) { return sgn(l2.angle()-l1.angle())<0; } inline bool cmp_halfplane(halfplane p1,halfplane p2) { int res=sgn(p1.angle()-p2.angle()); if (!res)return !p2.rightside(p1.ps); return res<0; } halfplane hpi_que[MAXN]; point hpi_pt_que[MAXN]; void halfplane_intersection(vector<halfplane> &vec,vector<point> &res) { sort(vec.begin(),vec.end(),cmp_halfplane); res.clear(); hpi_que[0]=vec[0]; int head=0,tail=0; point pt; for (register int i=1;i<(int)vec.size();i++) { if (parallel(vec[i],vec[i-1]))continue; while (head<tail && vec[i].rightside(hpi_pt_que[tail-1])) tail--; while (head<tail && vec[i].rightside(hpi_pt_que[head])) head++; hpi_que[++tail]=vec[i]; if (!sgn(det(hpi_que[tail],hpi_que[tail-1])) && hpi_que[tail].rightside(hpi_que[tail-1].ps)) { res.clear();return ; } hpi_pt_que[tail-1]=crossover(hpi_que[tail],hpi_que[tail-1]); } while (head<tail && hpi_que[head].rightside(hpi_pt_que[tail-1])) tail--; while (head<tail && hpi_que[tail].rightside(hpi_pt_que[head])) head++; if (head==tail) return; for (register int i=head;i<tail;i++) res.push_back(hpi_pt_que[i]); if (tail-1>head) res.push_back(crossover(hpi_que[head],hpi_que[tail])); return ; } real area(vector<point> &vec) { register real ans=0; for (register int i=0;i<(int)vec.size();i++) { ans+=area(point(0,0),vec[i],vec[(i+1)%vec.size()]); } return abs(ans); } void convex_hull(vector<point> &vec,vector<point> &res) { res.clear(); res.push_back(vec[0]); for (int i=1;i<(int)vec.size();i++) { while (res.size()>1 && !(line(res[res.size()-2],res[res.size()-1])).leftside(vec[i])) res.pop_back(); res.push_back(vec[i]); } int h=(int)vec.size(); for (int i=(int)vec.size()-1;i>=0;i++) { while ((int)res.size()>h && !(line(res[res.size()-2],res[res.size()-1])).leftside(vec[i])) res.pop_back(); res.push_back(vec[i]); } res.pop_back(); } class circle { public: point ct; real r; circle(){ct=point(0,0),r=0;}; circle(point ct,real r):ct(ct),r(r){}; circle(point p1,point p2,point p3) { line l1=line(p1,p2).mid_vertical(); line l2=line(p1,p3).mid_vertical(); ct=crossover(l1,l2); r=dis(ct,p1); } bool inside(point pt); bool on_border(point pt); bool outside(point pt); }; bool circle::inside(point pt) { return sgn(r-dis(pt,ct))>0; } bool circle::on_border(point pt) { return sgn(r-dis(pt,ct))==0; } bool circle::outside(point pt) { return sgn(r-dis(pt,ct))<0; } } using namespace geometry; int topv=-1; vector<halfplane> vv; vector<point> ans; point pl[MAXN]; int main() { freopen("input.txt","r",stdin); int i; int n; scanf("%d",&n); for (i=0;i<n;i++) pl[i].read(); int l=0,r=n/2,mid; while (l+1<r) { mid=(l+r)>>1; vv.clear(); for (i=0;i<n;i++) vv.push_back(line(pl[(i+mid+1)%n],pl[i])); halfplane_intersection(vv,ans); if (sgn(area(ans)>0)) { l=mid; }else { r=mid; } } printf("%d\n",r); }
bzoj1336
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<deque> using namespace std; #define MAXN 510000 namespace geometry { typedef long double real; const real pi=3.14159265358979323846264338; const real eps=1e-10; inline real sqr(real x) { return x*x; } inline int sgn(real x) { if (abs(x)<eps)return 0; return x<0?-1:1; } class point { public: real x,y; point() { x=y=0; } point(real x,real y):x(x),y(y){}; void read() { double xx,yy; scanf("%lf%lf\n",&xx,&yy); x=xx;y=yy; } void print() { printf("Point:[%.2lf,%.2lf]\n",(double)x,(double)y); } }; real dis(point p1,point p2) { return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y)); } bool cmp_point_position(point p1,point p2) { if (p1.y!=p2.y)return p1.y<p2.y; return p1.x<p2.x; } point mid_point(point p1,point p2) { return point((p1.x+p2.x)/2,(p1.y+p2.y)/2); } class line { public: point ps; point pt; line(){} line(point ps,point pt):ps(ps),pt(pt){} line(point ps,real dx,real dy); real len(); real angle(); bool leftside(point pp); void print(); point mid_point(); line mid_vertical(); }; real dot(line l1,line l2) { return (l1.pt.x-l1.ps.x)*(l2.pt.x-l2.ps.x) +(l1.pt.y-l1.ps.y)*(l2.pt.y-l2.ps.y); } real det(line l1,line l2) { return (l1.pt.x-l1.ps.x)*(l2.pt.y-l2.ps.y) - (l1.pt.y-l1.ps.y)*(l2.pt.x-l2.ps.x); } line::line(point ps,real dx,real dy) { this->ps=ps; this->pt.x=ps.x+dx; this->pt.y=ps.y+dy; } real line::len() { return sqrt(sqr(pt.x-ps.x)+sqr(pt.y-ps.y)); } real line::angle() { return atan2(pt.x-ps.x,pt.y-ps.y); /* if (pt.y>=ps.y) return -(pt.x-ps.x)/len(); else return (pt.x-ps.x)/len()+1e5;*/ /* if (pt.y>=ps.y) return acos((pt.x-ps.x)/len()); else return 2*pi-acos((pt.x-ps.x)/len()); */ } bool line::leftside(point pp) { return sgn(det(line(pp,ps),*this))>0; } void line::print() { printf("Line:[%.2lf,%.2lf] -> [%.2lf,%.2lf]\n",(double)ps.x,(double)ps.y,(double)pt.x,(double)pt.y); } point line::mid_point() { return point((ps.x+pt.x)/2,(ps.y+pt.y)/2); } line line::mid_vertical() { return line(mid_point(),pt.y-ps.y,ps.x-pt.x); } real operator *(line l1,line l2) { return det(l1,l2); } line operator -(point p1,point p2) { return line(p2,p1); } bool parallel(line l1,line l2) { return sgn(det(l1,l2))==0; } point crossover(line l1,line l2) { real s1=det(l1,l2.ps-l1.ps); real s2=-det(l1,l2.pt-l1.ps); return point(l2.ps.x+s1/(s1+s2)*(l2.pt.x-l2.ps.x), l2.ps.y+s1/(s1+s2)*(l2.pt.y-l2.ps.y)); } real area(point p1,point p2,point p3) { return (p2-p1)*(p3-p1)/2; } typedef line halfplane; bool cmp_line_angle(line l1,line l2) { return sgn(l2.angle()-l1.angle())<0; } bool cmp_halfplane(halfplane p1,halfplane p2) { int res=sgn(p1.angle()-p2.angle()); if (!res)return p2.leftside(p1.ps); return sgn(res)<0; } void halfplane_intersection(vector<halfplane> vec,vector<point> &res) { sort(vec.begin(),vec.end(),cmp_halfplane); /*for (int i=0;i<(int)vec.size();i++) { vec[i].print(); printf("%.5lf\n",(double)vec[i].angle()); }*/ deque<halfplane> q; deque<point> ans; q.clear(),ans.clear(); // vec[0].print(); // printf("%.5lf\n",(double)vec[0].angle()); point pt; q.push_back(vec[0]); for (int i=1;i<(int)vec.size();i++) { // vec[i].print(); // printf("%.5lf\n",(double)vec[i].angle()); if (parallel(vec[i],vec[i-1]))continue; while (ans.size() && !vec[i].leftside(ans.back())) { ans.pop_back(); q.pop_back(); } while (ans.size() && !vec[i].leftside(ans.front())) { ans.pop_front(); q.pop_front(); } if (parallel(vec[i],q.back())) { res.clear(); return ; } pt=crossover(vec[i],q.back()); ans.push_back(pt); q.push_back(vec[i]); } bool flag=true; while (flag) { flag=false; while (ans.size() && !q.front().leftside(ans.back())) ans.pop_back(),q.pop_back(),flag=true; while (ans.size() && !q.back().leftside(ans.front())) ans.pop_front(),q.pop_front(),flag=true; } if (q.size()>=2) { pt=crossover(q.back(),q.front()); ans.push_back(pt); } res=vector<point>(ans.begin(),ans.end()); return ; } real area(vector<point> &vec) { real ans=0; for (int i=0;i<(int)vec.size();i++) { ans+=area(point(0,0),vec[i],vec[(i+1)%vec.size()]); } return abs(ans); } void convex_hull(vector<point> vec,vector<point> &res) { sort(vec.begin(),vec.end(),cmp_point_position); res.clear(); res.push_back(vec[0]); for (int i=1;i<vec.size();i++) { while (res.size()>1 && !(line(res[res.size()-2],res[res.size()-1])).leftside(vec[i])) res.pop_back(); res.push_back(vec[i]); } int h=vec.size(); for (int i=vec.size()-1;i>=0;i++) { while (res.size()>h && !(line(res[res.size()-2],res[res.size()-1])).leftside(vec[i])) res.pop_back(); res.push_back(vec[i]); } res.pop_back(); } class circle { public: point ct; real r; circle(){ct=point(0,0),r=0;}; circle(point ct,real r):ct(ct),r(r){}; circle(point p1,point p2,point p3) { line l1=line(p1,p2).mid_vertical(); line l2=line(p1,p3).mid_vertical(); ct=crossover(l1,l2); r=dis(ct,p1); } bool inside(point pt); bool on_border(point pt); bool outside(point pt); }; bool circle::inside(point pt) { return sgn(r-dis(pt,ct))>0; } bool circle::on_border(point pt) { return sgn(r-dis(pt,ct))==0; } bool circle::outside(point pt) { return sgn(r-dis(pt,ct))<0; } }; using namespace geometry; int topv=-1; point pl[MAXN]; int main() { freopen("input.txt","r",stdin); int i,j,k; int n; scanf("%d",&n); for (i=0;i<n;i++) pl[i].read(); for (i=0;i<n*2;i++) swap(pl[rand()%n],pl[rand()%n]); circle cnow; for (i=0;i<n;i++) { if (cnow.outside(pl[i])) { cnow=circle(pl[i],0); for (j=0;j<i;j++) { if (cnow.outside(pl[j])) { cnow.ct=mid_point(pl[i],pl[j]); cnow.r=dis(pl[i],pl[j])/2; for (k=0;k<j;k++) { if (cnow.outside(pl[k])) { cnow=circle(pl[i],pl[j],pl[k]); } } } } } } printf("%.10lf\n",(double)cnow.r); printf("%.10lf %.10lf\n",(double)cnow.ct.x,(double)cnow.ct.y); }
poj 2451
必须交c++,如果用g++会wa,我在提交界面刷了六页的屏。。。。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<deque> using namespace std; #define MAXN 51000 namespace geometry { typedef long double real; const real pi=3.1415926535897; const real eps=1e-8; inline real sqr(real x) { return x*x; } inline int sgn(real x) { if (abs(x)<eps)return 0; return x<0?-1:1; } class point { public: real x,y; point(){x=y=0;} point(real x,real y):x(x),y(y){}; void read(); void print(); }; inline void point::read() { double xx,yy; scanf("%lf%lf\n",&xx,&yy); x=xx;y=yy; } inline void point::print() { printf("Point:[%.2lf,%.2lf]\n",(double)x,(double)y); } inline real dis(point p1,point p2) { return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y)); } inline bool cmp_point_position(point p1,point p2) { if (p1.y!=p2.y)return p1.y<p2.y; return p1.x<p2.x; } class line { public: point ps; point pt; line(point ps,point pt):ps(ps),pt(pt){} line(){} real len(); real angle(); bool leftside(point pp); bool rightside(point pp); void print(); }; inline real dot(line& l1,line& l2) { return (l1.pt.x-l1.ps.x)*(l2.pt.x-l2.ps.x) +(l1.pt.y-l1.ps.y)*(l2.pt.y-l2.ps.y); } inline real det(line l1,line l2) { return (l1.pt.x-l1.ps.x)*(l2.pt.y-l2.ps.y) - (l1.pt.y-l1.ps.y)*(l2.pt.x-l2.ps.x); } inline real line::len() { return sqrt(sqr(pt.x-ps.x)+sqr(pt.y-ps.y)); } inline real line::angle() { //return atan2(pt.x-ps.x,pt.y-ps.y); /* if (pt.y>=ps.y) return -(pt.x-ps.x)/len(); else return (pt.x-ps.x)/len()+10;*/ if (pt.y>=ps.y) return acos((pt.x-ps.x)/len()); else return 2*pi-acos((pt.x-ps.x)/len()); } inline bool line::leftside(point pp) { return sgn(det(line(pp,ps),*this))>0; } inline bool line::rightside(point pp) { return sgn(det(line(pp,ps),*this))<0; } inline void line::print() { printf("Line:[%.2lf,%.2lf] -> [%.2lf,%.2lf]\n",(double)ps.x,(double)ps.y,(double)pt.x,(double)pt.y); } inline real operator *(line l1,line l2) { return det(l1,l2); } inline line operator -(point p1,point p2) { return line(p2,p1); } inline bool parallel(line l1,line l2) { return sgn(l1.angle()-l2.angle())==0; //return sgn(det(l1,l2))==0; } inline point crossover(line l1,line l2) { if (!sgn(det(l1,l2)))throw 1; real s1=det(l1,l2.ps-l1.ps); real s2=-det(l1,l2.pt-l1.ps); return point(l2.ps.x+s1/(s1+s2)*(l2.pt.x-l2.ps.x), l2.ps.y+s1/(s1+s2)*(l2.pt.y-l2.ps.y)); } inline real area(point p1,point p2,point p3) { return det(line(p2,p1),line(p3,p1))/2; } typedef line halfplane; inline bool cmp_line_angle(line l1,line l2) { return sgn(l2.angle()-l1.angle())<0; } inline bool cmp_halfplane(halfplane p1,halfplane p2) { int res=sgn(p1.angle()-p2.angle()); if (!res)return !p2.rightside(p1.ps); return res<0; } halfplane q[MAXN]; point qp[MAXN]; void halfplane_intersection(vector<halfplane> &vec,vector<point> &res) { sort(vec.begin(),vec.end(),cmp_halfplane); int x=1; //for (int i=0;i<(int)vec.size();i++) // { // vec[i].print(); //printf("%.5lf\n",(double)vec[i].angle()); // } // vec[0].print(); // printf("%.5lf\n",(double)vec[0].angle()); res.clear(); q[0]=vec[0]; int head=0,tail=0; point pt; //vec[0].print(); for (register int i=1;i<(int)vec.size();i++) { //vec[i].print(); if (parallel(vec[i],vec[i-1]))continue; while (head<tail && vec[i].rightside(qp[tail-1])) tail--; while (head<tail && vec[i].rightside(qp[head])) head++; q[++tail]=vec[i]; if (!sgn(det(q[tail],q[tail-1])) && q[tail].rightside(q[tail-1].ps)) { res.clear();return ; } qp[tail-1]=crossover(q[tail],q[tail-1]); } while (head<tail && q[head].rightside(qp[tail-1])) tail--; while (head<tail && q[tail].rightside(qp[head])) head++; if (head==tail) { return; } for (register int i=head;i<tail;i++) res.push_back(qp[i]); if (tail-1>head)//??? res.push_back(crossover(q[head],q[tail])); return ; } real area(vector<point> &vec) { register real ans=0; for (register int i=0;i<(int)vec.size();i++) { ans+=area(point(0,0),vec[i],vec[(i+1)%vec.size()]); } return abs(ans); } void convex_hull(vector<point> &vec,vector<point> &res) { res.clear(); res.push_back(vec[0]); for (int i=1;i<(int)vec.size();i++) { while (res.size()>1 && !(line(res[res.size()-2],res[res.size()-1])).leftside(vec[i])) res.pop_back(); res.push_back(vec[i]); } int h=vec.size(); for (int i=(int)vec.size()-1;i>=0;i++) { while (res.size()>h && !(line(res[res.size()-2],res[res.size()-1])).leftside(vec[i])) res.pop_back(); res.push_back(vec[i]); } res.pop_back(); } } using namespace geometry; int topv=-1; vector<halfplane> vv; vector<point> ans; point pl[MAXN]; int main() { //freopen("input.txt","r",stdin); int i; int n; while (~scanf("%d",&n) && ~n) { point pt; vv.clear(); vv.push_back(line(point(0,0),point(10000,0))); vv.push_back(line(point(10000,0),point(10000,10000))); vv.push_back(line(point(10000,10000),point(0,10000))); vv.push_back(line(point(0,10000),point(0,0))); double a,b,c,d; for (i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&a,&b,&c,&d); vv.push_back(line(point(a,b),point(c,d))); } // crossover(vv[4],vv[5],pt); halfplane_intersection(vv,ans); // for (i=0;i<(int)ans.size();i++) // ans[i].print(); printf("%.1lf\n",(double)area(ans)); } }
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载
本博客已停用,新博客地址:http://mhy12345.xyz