新模板


#include<bits/stdc++.h> using namespace std; const double eps=1e-8; const double pi=acos(-1.0); inline double sqr(double x){ return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } void output(){ printf("%.2f %.2f\n",x,y); } friend istream &operator >>(istream &os,Point &b){os>>b.x>>b.y;return os; } friend ostream &operator <<(ostream &os,Point &b){os<<b.x<<' '<<b.y;return os; } bool operator ==(const Point &b)const{return ( dcmp(x-b.x)==0&&dcmp(y-b.y)==0); } bool operator !=(const Point &b)const{return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0)); } bool operator <(const Point &b)const {return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); } double operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 double 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 *(double a) { return Point(x*a,y*a); } Point operator /(double a) { return Point(x/a,y/a); } double len2() { return sqr(x)+sqr(y); }//长度平方 double len() { return sqrt(len2()); }//长度 double polar(){ return atan2(y,x); }//向量的极角 //返回与x轴正向夹角(-pi~pi] Point change_len(double r){ //转化为长度为r的向量 double l=len(); if(dcmp(l)==0) return *this; //零向量 return Point(x*r/l,y*r/l); } Point rotate_left() { return Point(-y,x); }//逆时针旋转90度 Point rotate_right(){ return Point(y,-x); }//顺时针旋转90度 Point rotate(Point p,double ang){ //绕点p逆时针旋转ang度 Point v=(*this)-p; double c=cos(ang),s=sin(ang); return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); } Point normal(){ return Point(-y/len(),x/len()); }//单位化,逆时针旋转90° }; inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 inline double dot(Point a,Point b) { return a.x*b.x+a.y*b.y; }//点积 double rad(Point a,Point b) { return fabs(atan2(fabs(cross(a,b)),dot(a,b))); }//两个向量的夹角 double area2(Point A, Point B, Point C) { return cross(B-A, C-A); } // 四边形面积 bool is_parallel(Point a,Point b) { double p=rad(a,b);return dcmp(p)==0||dcmp(p-pi)==0; }//判断向量是否平行 struct Line{ Point s,e; Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 Line(Point p,double ang){ //一个点和斜率(弧度制)确定直线 s=p; if(dcmp(ang-pi/2)==0){ e=s+Point(0,1); } else { e=s+Point(1,tan(ang)); } } void input(){ s.input(); e.input(); } Point operator &(const Line &b)const{ //求两直线交点 Point res=s; double 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; } }; double polygon_area(vector<Point> p){ //多边形的有向面积,加上绝对值就是面积 正值表示输入点按照逆时针 否则为顺时针 int n=p.size(); double area=0; for(int i=1;i<n-1;i++) area+=cross(p[i]-p[0],p[i+1]-p[0]); return fabs(area/2); } double PolygonLength(vector<Point> vp){ int m=vp.size(); double area=0; for(int i=0;i<m;i++) area+=dis(vp[i],vp[(i+1)%m]); return fabs(area/2); } int main(){ }
借用的模板 平面直线图
求直线平面直线图中第K大的多边形 的面积 n*n将所有的边添加到图里 再逆时针求出所有多边形面积 排序输出第K大


// thanks to DD_BOND #include<bits/stdc++.h> #define fi first #define se second #define pb push_back typedef long long ll; using namespace std; const int MAXN=1e6+10; const double eps=1e-8; const double pi=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3f; inline int dcmp(double x){ if(fabs(x)<eps) return 0; return (x>0? 1: -1); } inline double sqr(double x){ return x*x; } struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } void output(){ printf("%.2f %.2f\n",x,y); } bool operator ==(const Point &b)const{ return (dcmp(x-b.x)==0&&dcmp(y-b.y)==0); } bool operator !=(const Point &b)const{ return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0)); } bool operator <(const Point &b)const{ return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); } double operator ^(const Point &b)const{ //叉积 return x*b.y-y*b.x; } double 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 *(double a){ return Point(x*a,y*a); } Point operator /(double a){ return Point(x/a,y/a); } double len2(){ //长度平方 return sqr(x)+sqr(y); } double len(){ //长度 return sqrt(len2()); } double polar(){ //向量的极角 return atan2(y,x); //返回与x轴正向夹角(-pi~pi] } }; inline double cross(Point a,Point b){ //叉积 return a.x*b.y-a.y*b.x; } inline double dot(Point a,Point b){ //点积 return a.x*b.x+a.y*b.y; } double rad(Point a,Point b){ //两个向量的夹角 return fabs(atan2(fabs(cross(a,b)),dot(a,b))); } bool is_parallel(Point a,Point b){ //判断向量是否平行 double p=rad(a,b); return dcmp(p)==0||dcmp(p-pi)==0; } struct Line{ Point s,e; Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 Line(Point p,double ang){ //一个点和斜率(弧度制)确定直线 s=p; if(dcmp(ang-pi/2)==0){ e=s+Point(0,1); } else{ e=s+Point(1,tan(ang)); } } void input(){ s.input(); e.input(); } Point operator &(const Line &b)const{ //求两直线交点 Point res=s; double 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; } }; double polygon_area(vector<Point> p){ //多边形的有向面积,加上绝对值就是面积 正值表示输入点按照逆时针 否则为顺时针 int n=p.size(); double area=0; for(int i=1;i<n-1;i++) area+=cross(p[i]-p[0],p[i+1]-p[0]); return fabs(area/2); } struct PSLG{ //平面直线图 处理平面内所有直线围成的所有多边形 传入直线交点之间的每条线段 struct Edge{ int from,to; double ang; Edge(){ ang=from=to=0; } Edge(int s,int t,double a){ from=s,to=t,ang=a; } }; int n,m,face_cnt; //平面个数 包括外面最大的多边形 double area[MAXN]; //每个多边形面积 Point point[MAXN]; //平面内所有的点 vector<Edge>edge; vector<int>G[MAXN]; vector<vector<Point> >face; int vis[2*MAXN],left[2*MAXN],pre[2*MAXN]; //left表示这条边的左侧属于哪个面 void Init(){ face.clear(); edge.clear(); for(int i=0;i<n;i++) G[i].clear(); n=m=0; } PSLG(){ Init(); } 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-2); G[to].pb(m-1); } void Build(){ for(int u=0;u<n;u++){ int d=G[u].size(); for(int i=0;i<d;i++) for(int j=i+1;j<d;j++) if(edge[G[u][i]].ang>edge[G[u][j]].ang) swap(G[u][i],G[u][j]); for(int i=0;i<d;i++) pre[G[u][(i+1)%d]]=G[u][i]; //从u出发的i条边顺时针旋转的第一条边是pre[i] } face_cnt=0; memset(vis,0,sizeof(vis)); for(int u=0;u<n;u++){ for(int i=0;i<G[u].size();i++){ int e=G[u][i]; if(!vis[e]){ face_cnt++; vector<Point> polygon; while(1){ vis[e]=1; left[e]=face_cnt; int from=edge[e].from; polygon.pb(point[from]); e=pre[e^1]; //逆时针旋转最多的一条边即为顺时针转动的第一条边 if(e==G[u][i]) break; } face.pb(polygon); } } } for(int i=0;i<face_cnt;i++) area[i]=polygon_area(face[i]); } }; PSLG pslg; Line line[MAXN]; vector<pair<double,int> >point[MAXN]; int main(void){ int n; scanf("%d",&n); for(int i=0;i<n;i++) line[i].input(); for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++) if(!is_parallel(line[i].e-line[i].s,line[j].e-line[j].s)){ Point inter=line[i]&line[j]; pslg.point[pslg.n++]=inter; point[i].pb({dot(inter-line[i].s,line[i].e-line[i].s),pslg.n-1}); point[j].pb({dot(inter-line[j].s,line[j].e-line[j].s),pslg.n-1}); } sort(point[i].begin(),point[i].end()); for(int j=1;j<point[i].size();j++) pslg.AddEdge(point[i][j-1].se,point[i][j].se); } pslg.Build(); sort(pslg.area,pslg.area+pslg.face_cnt); printf("%d %.6f %.6f\n",pslg.face_cnt-1,pslg.area[pslg.face_cnt-2],pslg.area[0]); int q; scanf("%d",&q); while(q--){ int p; scanf("%d",&p); if(p>=pslg.face_cnt) puts("Invalid question"); else printf("%.6f\n",pslg.area[pslg.face_cnt-p-1]); } return 0; }


#include<bits/stdc++.h> #define fi first #define se second #define pb push_back typedef long long ll; using namespace std; const int MAXN=1e6+10; const double eps=1e-8; const double pi=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3f; inline int dcmp(double x){ if(fabs(x)<eps) return 0; return (x>0? 1: -1); } inline double sqr(double x){ return x*x; } struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } void output(){ printf("%.2f %.2f\n",x,y); } friend istream &operator >>(istream &os,Point &b){ os>>b.x>>b.y; return os; } friend ostream &operator <<(ostream &os,Point &b){ os<<b.x<<' '<<b.y; return os; } bool operator ==(const Point &b)const{ return (dcmp(x-b.x)==0&&dcmp(y-b.y)==0); } bool operator !=(const Point &b)const{ return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0)); } bool operator <(const Point &b)const{ return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); } double operator ^(const Point &b)const{ //叉积 return x*b.y-y*b.x; } double 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 *(double a){ return Point(x*a,y*a); } Point operator /(double a){ return Point(x/a,y/a); } double len2(){ //长度平方 return sqr(x)+sqr(y); } double len(){ //长度 return sqrt(len2()); } double polar(){ //向量的极角 return atan2(y,x); //返回与x轴正向夹角(-pi~pi] } Point change_len(double r){ //转化为长度为r的向量 double l=len(); if(dcmp(l)==0) return *this; //零向量 return Point(x*r/l,y*r/l); } Point rotate_left(){ //逆时针旋转90度 return Point(-y,x); } Point rotate_right(){ //顺时针旋转90度 return Point(y,-x); } Point rotate(Point p,double ang){ //绕点p逆时针旋转ang度 Point v=(*this)-p; double c=cos(ang),s=sin(ang); return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); } Point normal(){ //单位化,逆时针旋转90° return Point(-y/len(),x/len()); } }; inline double cross(Point a,Point b){ //叉积 return a.x*b.y-a.y*b.x; } inline double dot(Point a,Point b){ //点积 return a.x*b.x+a.y*b.y; } double rad(Point a,Point b){ //两个向量的夹角 return fabs(atan2(fabs(cross(a,b)),dot(a,b))); } bool is_parallel(Point a,Point b){ //判断向量是否平行 double p=rad(a,b); return dcmp(p)==0||dcmp(p-pi)==0; } struct Line{ Point s,e; Line(){} Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 Line(Point p,double ang){ //一个点和斜率(弧度制)确定直线 s=p; if(dcmp(ang-pi/2)==0){ e=s+Point(0,1); } else{ e=s+Point(1,tan(ang)); } } Line(double a,double b,double c){ //ax+by+c=0 if(dcmp(a)==0){ s=Point(0,-c/b); e=Point(1,-c/b); } else if(dcmp(b)==0){ s=Point(-c/a,0); e=Point(-c/a,1); } else{ s=Point(0,-c/b); e=Point(1,(-c-a)/b); } } void input(){ s.input(); e.input(); } void adjust(){ if(e<s) swap(e,s); } double polar(){ //极角 return atan2(e.y-s.y,e.x-s.x); //返回与x轴正向夹角(-pi~pi] } double angle(){ //倾斜角 double k=atan2(e.y-s.y,e.x-s.x); if(dcmp(k)<0) k+=pi; if(dcmp(k-pi)==0) k-=pi; return k; } Point operator &(const Line &b)const{ //求两直线交点 Point res=s; double 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; } }; double polygon_area(vector<Point> p){ //多边形的有向面积,加上绝对值就是面积 正值表示输入点按照逆时针 否则为顺时针 int n=p.size(); double area=0; for(int i=1;i<n-1;i++) area+=cross(p[i]-p[0],p[i+1]-p[0]); return fabs(area/2); } struct PSLG{ //平面直线图 处理平面内所有直线围成的所有多边形 传入直线交点之间的每条线段 struct Edge{ int from,to; double ang; Edge(){ ang=from=to=0; } Edge(int s,int t,double a){ from=s,to=t,ang=a; } }; int n,m,face_cnt; //平面个数 包括外面最大的多边形 double area[MAXN]; //每个多边形面积 Point point[MAXN]; //平面内所有的点 vector<Edge>edge; vector<int>G[MAXN]; vector<vector<Point> >face; int vis[2*MAXN],left[2*MAXN],pre[2*MAXN]; //left表示这条边的左侧属于哪个面 void Init(){ face.clear(); edge.clear(); for(int i=0;i<n;i++) G[i].clear(); n=m=0; } PSLG(){ Init(); } 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-2); G[to].pb(m-1); } void Build(){ for(int u=0;u<n;u++){ int d=G[u].size(); for(int i=0;i<d;i++) for(int j=i+1;j<d;j++) if(edge[G[u][i]].ang>edge[G[u][j]].ang) swap(G[u][i],G[u][j]); for(int i=0;i<d;i++) pre[G[u][(i+1)%d]]=G[u][i]; //从u出发的i条边顺时针旋转的第一条边是pre[i] } face_cnt=0; memset(vis,0,sizeof(vis)); for(int u=0;u<n;u++){ for(int i=0;i<G[u].size();i++){ int e=G[u][i]; if(!vis[e]){ face_cnt++; vector<Point> polygon; while(1){ vis[e]=1; left[e]=face_cnt; int from=edge[e].from; polygon.pb(point[from]); e=pre[e^1]; //逆时针旋转最多的一条边即为顺时针转动的第一条边 if(e==G[u][i]) break; } face.pb(polygon); } } } for(int i=0;i<face_cnt;i++) area[i]=polygon_area(face[i]); } }; PSLG pslg; Line line[MAXN]; vector<pair<double,int> >point[MAXN]; int main(void){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); //freopen("/My_Mac/Resource/Project__C++/testdata.in","r",stdin); //freopen("/My_Mac/Resource/Project__C++/testdata.out","w",stdout); int n; scanf("%d",&n); for(int i=0;i<n;i++) line[i].input(); for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++) if(!is_parallel(line[i].e-line[i].s,line[j].e-line[j].s)){ Point inter=line[i]&line[j]; pslg.point[pslg.n++]=inter; point[i].pb({dot(inter-line[i].s,line[i].e-line[i].s),pslg.n-1}); point[j].pb({dot(inter-line[j].s,line[j].e-line[j].s),pslg.n-1}); } sort(point[i].begin(),point[i].end()); for(int j=1;j<point[i].size();j++) pslg.AddEdge(point[i][j-1].se,point[i][j].se); } pslg.Build(); sort(pslg.area,pslg.area+pslg.face_cnt); printf("%d %.6f %.6f\n",pslg.face_cnt-1,pslg.area[pslg.face_cnt-2],pslg.area[0]); int q; scanf("%d",&q); while(q--){ int p; scanf("%d",&p); if(p>=pslg.face_cnt) puts("Invalid question"); else printf("%.6f\n",pslg.area[pslg.face_cnt-p-1]); } return 0; }
自己的主要模板吧 别人的不习惯 点 线 面 的定义


#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> #define ll long long using namespace std; const int maxn=50; const double pi=acos(-1.0); const double D_MAX=1e100; const double D_MIN=-1e100; const double eps=1e-9; int sgn(double x){ if(fabs(x) < eps) return 0; if(x >0) return 1; return -1; } int dcmp(double x, double y) { // judge (x-y) if(fabs(x - y) < eps) return 0; if(x > y) return 1; return -1; } struct Point { // double pan duan double x,y; Point(double a=0,double b=0) { x=a;y=b; }; }; typedef Point Vector; Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); } // 向量相加 Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成 double operator * (Vector A, Vector B){ return A.x*B.x-A.y*B.y; } // 点积 double operator ^ (Vector A, Vector B){ return A.x*B.y-A.y*B.x; } // 叉积 Vector __pos(Point a,Point b) {return b-a; } // a->b向量生成 struct Line{ Point a,b; // form a to b Vector p; // a-->b double ang; Line(Point x=Point(0,0),Point y=Point(0,0) ) { a=x; b=y; p=b-a; // a_>b ang=atan2(p.y,p.x); } }; int main(){ Point a={5,4}; Point b={5,5}; Line x={a,b}; cout<<x.a.x<<" "<<x.a.y<<endl; cout<<x.b.x<<" "<<x.b.y<<endl; cout<<x.ang<<" "<<x.p.x<<" "<<x.p.y<<endl; }
功能定义 点积 叉积 距离


#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> #define ll long long using namespace std; const int maxn=50; const double pi=acos(-1.0); const double D_MAX=1e100; const double D_MIN=-1e100; const double eps=1e-9; int sgn(double x){ if(fabs(x) < eps) return 0; if(x >0) return 1; return -1; } int dcmp(double x, double y) { // judge (x-y) if(fabs(x - y) < eps) return 0; if(x > y) return 1; return -1; } struct Point { // double pan duan double x,y; Point(double a=0,double b=0) { x=a;y=b; }; }; typedef Point Vector; Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); } // 向量相加 Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成 double operator * (Vector A, Vector B){ return A.x*B.x-A.y*B.y; } // 点积 double operator ^ (Vector A, Vector B){ return A.x*B.y-A.y*B.x; } // 叉积 Vector __pos(Point a,Point b) {return b-a; } // a->b向量生成 double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } // 点积 double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } // 叉积 double Length(Vector A) { return sqrt(Dot(A, A)); } // 向量长度 double Angle(Vector A, Vector B) { return acos(Dot(A, B)/Length(A)/Length(B)); } // 角度 double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A); } // 四边形面积 double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} Vector Normal(Vector A) { double L = Length(A); return Vector(-A.y/L, A.x/L); } //rad为弧度 且为逆时针旋转的角 bool ToLeftTest(Point a,Point b,Point c){ return Cross(b - a, c - b) > 0; } //向量A左转90°的单位法向量 struct Line{ Point a,b; // form a to b Vector p; // a-->b double ang; Line(Point x=Point(0,0),Point y=Point(0,0) ) { a=x; b=y; p=b-a; // a_>b ang=atan2(p.y,p.x); } }; double PolygonArea(vector<Point> vp){ int m=vp.size(); Point c; double area=0; for(int i=0;i<m;i++){ area+=Cross(vp[i]-c,vp[(i+1)%m]-c); } return area/2; } double PolygonLength(vector<Point> vp){ int m=vp.size(); Point c; double area=0; for(int i=0;i<m;i++){ area+=dis(vp[i],vp[(i+1)%m]); } return area/2; } int main(){ Point a={5,4}; Point b={5,5}; Line x={a,b}; cout<<x.a.x<<" "<<x.a.y<<endl; cout<<x.b.x<<" "<<x.b.y<<endl; cout<<x.ang<<" "<<x.p.x<<" "<<x.p.y<<endl; }
直线相交检测 2-重合 1-相交 0-不相交 两点式 double 类型


int check_line_line(Line A,Line B) { Point a=A.a; Point b=A.b; Point c=B.a; Point d=B.b; double A1=b.y-a.y,B1=-(b.x-a.x),C1=b.y*a.x-b.x*a.y; double A2=d.y-c.y,B2=-(d.x-c.x),C2=d.y*c.x-d.x*c.y; double k=A1*B2-A2*B1; if(fabs(k)<eps) { if(fabs( C2*A1-C1*A2)<eps && fabs(B1*C2-C1*B2)<eps ) return 2 else return 0; } return 1; }
直线相交求交点 1-相交情况求交点 两点式 double 类型


Point line_line(Line A,Line B) { Point a=A.a; Point b=A.b; Point c=B.a; Point d=B.b; double A1=b.y-a.y,B1=-(b.x-a.x),C1=b.y*a.x-b.x*a.y; double A2=d.y-c.y,B2=-(d.x-c.x),C2=d.y*c.x-d.x*c.y; double k=A1*B2-A2*B1; double x=-(B1*C2-C1*B2)*1.000000000/k; double y= (A1*C2-C1*A2)*1.00000000/k; Point ans; ans.x=y; ans.y=y; return ans; }
poj 1269 两条直线相交 判断 ( 重合 相交 不相交 )


void XX(Line A,Line B) { Point a=A.a; Point b=A.b; Point c=B.a; Point d=B.b; double A1=b.y-a.y,B1=-(b.x-a.x),C1=b.y*a.x-b.x*a.y; double A2=d.y-c.y,B2=-(d.x-c.x),C2=d.y*c.x-d.x*c.y; double k=A1*B2-A2*B1; if(fabs(k)<eps) { if( fabs( C2*A1-C1*A2)<eps && fabs(B1*C2-C1*B2)<eps ) printf("LINE\n"); else printf("NONE\n"); } else { double x=-(B1*C2-C1*B2)*1.000000000/k; double y=(A1*C2-C1*A2)*1.00000000/k; printf("POINT %.2f %.2f\n",x,y); } }
线段相交 1-相交 0-不相交 (非严格相交 严格相交)


bool check_se_se_uff(Segment A,Segment B) { Point a=A.a; Point b=A.b;Point c=B.a; Point d=B.b; return Cross(a-c,a-d)*Cross(b-c,b-d)<=0 && Cross(c-a,c-b)*Cross(d-a,d-b)<=0 ; } bool check_se_se_ff(Segment A,Segment B){ Point a=A.a; Point b=A.b;Point c=B.a; Point d=B.b; return max(A.a.x,A.b.x) >= min(B.a.x,B.b.x) && max(B.a.x,B.b.x) >= min(A.a.x,A.b.x) && max(A.a.y,A.b.y) >= min(B.a.y,B.b.y) && max(B.a.y,B.b.y) >= min(A.a.y,A.b.y) && Cross(a-c,a-d)*Cross(b-c,b-d)<=0 && Cross(c-a,c-b)*Cross(d-a,d-b)<=0 ; }
线段交点求法同直线一样
hdu 3272 枚举中间ABCD P(ABCD)P


#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; const double pi=acos(-1.0); const double D_MAX=1e100; const double D_MIN=-1e100; const double eps=1e-9; int sgn(double x){ if(fabs(x) < eps)return 0; if(x >0) return 1; return -1; } int dcmp(double x, double y){ if(fabs(x - y) < eps) return 0; if(x > y) return 1;return -1;} void usehanshu(){double x;}//floor(x)向下取整函数ceil(x)向上取整函数round(x)四舍五入函数 struct Point { int x,y; Point(int a=0,int b=0) { x=a;y=b; }; }; struct Segment{ Point a,b; Segment(Point x=Point(0,0),Point y=Point(0,0) ) { a=x;b=y; }; }; struct Line { Point a,b; Line(Point x=Point(0,0),Point y=Point(0,0) ) { a=x;b=y; }; }; double dis(Point A,Point B) { return sqrt( 1.0*(A.x-B.x)*(A.x-B.x)+1.0*(A.y-B.y)*(A.y-B.y) ); } /*-----------show time ---------------------*/ int a[5]; double make_x(Point p,Point c){ if(p.y*c.y>0) p.y=-p.y; return dis(p,c); } double make_y(Point p,Point c){ if(p.x*c.x>0) p.x=-p.x; return dis(p,c); } double make_xy(Point p,Point c){ if(p.x*c.x>0) p.x=-p.x; if(p.y*c.y>0) p.y=-p.y; return dis(p,c); } int main(){ int T; scanf("%d",&T); while(T--){ double num=1e9+10; Point c; Point d; Point p; scanf("%d %d %d %d %d %d",&c.x,&c.y,&d.x,&d.y,&p.x,&p.y); for(int i=1;i<=4;i++) a[i]=i; do{ int t=0; Point w=p; double ans=0; for(int i=1;i<=4;i++){ if(a[i]==1 || a[i]==2 ) t+=a[i]; else if(a[i]==3){ if(t==0) ans+=dis(w,c); else if(t==1) ans+=make_x(w,c); else if(t==2) ans+=make_y(w,c); else ans+=make_xy(w,c); w=c; t=0; } else if(a[i]==4){ if(t==0) ans+=dis(w,d); else if(t==1) ans+=make_x(w,d); else if(t==2) ans+=make_y(w,d); else ans+=make_xy(w,d); w=d; t=0; } } if(t==0) ans+=dis(w,p); else if(t==1) ans+=make_x(w,p); else if(t==2) ans+=make_y(w,p); else ans+=make_xy(w,p); num=min(ans,num); } while(next_permutation(a+1,a+1+4)); printf("%.2f\n",num); } }
poj 1873 凸包


#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> #define ll long long using namespace std; const int maxn=1e5+10; struct Point { double x,y; Point(double a=0,double b=0) { x=a;y=b; }; }; typedef Point Vector; Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成 double Cross(Vector A, Vector B) { return A.x*B.y-A.y*B.x; } // 叉积 double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y) ); } Point pa[maxn]; int a[maxn]; int b[maxn]; bool up(Point a,Point b) { if(a.x!=b.x) return a.x<b.x; return a.y<b.y; } vector<Point> vs; vector<int> vp; vector<int> vc; double work(){ Point pa[60]; Point pt[60]; int n=vs.size(); for(int i=0;i<n;i++) pa[i]=vs[i]; sort(pa,pa+n,up); int m=0; for(int i=0;i<n;i++) { while(m>1 && Cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } int k=m; for(int i=n-2;i>=0;i--) { while(m>k && Cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } if(n>1) m--; double ans=0; for(int i=1;i<m;i++) ans+=dis(pt[i],pt[i+1]); ans+=dis(pt[m],pt[1]); return ans; } int main(){ int n; int tot=0; while(scanf("%d",&n) && n!=0){ for(int i=1;i<=n;i++){ scanf("%lf %lf",&pa[i].x,&pa[i].y); scanf("%d %d",&a[i],&b[i]); } vp.clear(); int ans1=0; int ans2=0; double ans3=0; for(int i=0;i<(1<<n);i++){ vs.clear(); vc.clear(); int value=0; int tree=0; int num=0; for(int j=1;j<=n;j++){ if(i&(1<<(j-1))){ // 砍掉 tree+=b[j]; vc.push_back(j); }else { // 剩余 value+=a[j]; vs.push_back(pa[j]); num++; } } double k=work(); ; if(tree>=k){ if(value>ans1){ ans1=value; ans2=num; ans3=tree-k; vp.clear(); for(int w=0;w<vc.size();w++) vp.push_back(vc[w]); } else if(value==ans1){ if(num>=ans2){ ans1=value; ans2=num; ans3=tree-k; vp.clear(); for(int w=0;w<vc.size();w++) vp.push_back(vc[w]); } } } } if(tot!=0) printf("\n"); printf("Forest %d\n",++tot); printf("Cut these trees:"); for(int i=0;i<vp.size();i++){ printf(" %d",vp[i]); } printf("\n"); printf("Extra wood: %.2f\n",ans3); } }
poj 1113 凸包


#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <cmath> using namespace std; const int maxn=1e5+10; const double PI=acos(-1.0); struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y) {}; }; typedef Point Vector; Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成 double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y) ); } double Cross(Vector B, Vector A) { return A.x*B.y-A.y*B.x; } // 叉积 Point pa[maxn]; Point pt[maxn]; bool up(Point a,Point b) { if(a.x!=b.x) return a.x<b.x; return a.y<b.y; } int main() { int n,r; scanf("%d %d",&n,&r); for(int i=0;i<n;i++) scanf("%lf %lf",&pa[i].x,&pa[i].y); sort(pa,pa+n,up); int m=0; for(int i=0;i<n;i++) { while(m>1 && Cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } int k=m; for(int i=n-2;i>=0;i--) { while(m>k && Cross(pt[m-1]-pt[m-2],pa[i]-pt[m-2])<=0) m--; pt[m++]=pa[i]; } if(n>1) m--; double ans=0; for(int i=1;i<m;i++) ans+=dis(pt[i],pt[i+1]); ans+=dis(pt[m],pt[1]); //cout<<ans<<" "<<PI<<endl; ans+=PI*r*2; printf("%.0f\n",ans); return 0; }
半平面交 https://blog.youkuaiyun.com/qq_40861916/article/details/83541403
https://blog.youkuaiyun.com/Richie_ll/article/details/70939711
poj 2007 凸包


#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> #define ll long long using namespace std; const int maxn=1e5+10; struct Point { double x,y; Point(double a=0,double b=0) { x=a;y=b; }; }; typedef Point Vector; Vector operator - (Point A, Point B){ return Vector(B.x-A.x, B.y-A.y); } // 向量生成 double Cross(Vector A, Vector B) { return A.x*B.y-A.y*B.x; } // 叉积 Point pa[maxn]; bool cmp1(Point a,Point b){ return atan2(a.y,a.x)<atan2(b.y,b.x); } bool cmp2(Point a,Point b){ Point c; return Cross(c-a,c-b)>0; } int main(){ Point s; scanf("%lf %lf",&s.x,&s.y); int tot=1; while(~scanf("%lf %lf",&pa[tot].x,&pa[tot].y) && pa[tot].x!=1100) {++tot; } //cout<<tot<<endl; sort(pa+1,pa+tot,cmp2); printf("(%.0f,%.0f)\n",s.x,s.y); for(int i=1;i<tot;i++){ printf("(%.0f,%.0f)\n",pa[i].x,pa[i].y); } }