zoukankan      html  css  js  c++  java
  • 计算几何题目总结 (只保证模板正确 代码过题)

    凸包

    poj  1113  Graham Scan 算法    极角排序+栈模拟

    //#include<bits/stdc++.h>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.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); }
        Point operator -(const Point &b)const {     return Point(x-b.x,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));}
    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;                               } //点积
    bool up(Point a,Point b){
        if(a.y==b.y) return a.x<b.x;
        return a.y<b.y;
    }
    bool cmp(Point a, Point b)//先按象限排序,再按极角排序,再按远近排序   (调精度 注意改成int或ll)
    {
        if (a.y == 0 && b.y == 0 && a.x*b.x <= 0)return a.x>b.x;
        if (a.y == 0 && a.x >= 0 && b.y != 0)return true;
        if (b.y == 0 && b.x >= 0 && a.y != 0)return false;
        if (b.y*a.y <= 0)return a.y>b.y;
        Point one;
        one.y = one.x = 0;
        return cross(one-a,one-b) > 0 || (cross(one-a,one-b) == 0 && a.x < b.x);
    }
    const int maxn=1e3+10;
    Point pa[maxn];
    int st[maxn];  //
    void Graham(int n,int r){
        sort(pa,pa+n,up);
        for(int i=1;i<n;i++) { pa[i]=pa[i]-pa[0]; }  pa[0]=pa[0]-pa[0];
        sort(pa+1,pa+n,cmp);
        st[0]=0;  st[1]=1;
        int top=1;
        for(int i=2;i<n;i++){
            while(top>=1 && cross(pa[st[top]]-pa[st[top-1]],pa[i]-pa[st[top]])<=0) top--;
            st[++top]=i;
        }
        double ans=0;
        for(int i=0;i<=top;i++){
            ans+=dis(pa[st[i]],pa[st[(i+1)%(top+1)]]);
        }
        printf("%.0f
    ",ans+pi*r*2);
    }
    int main(){
        int n; scanf("%d",&n);
        int r; scanf("%d",&r);
        for(int i=0;i<n;i++) scanf("%lf %lf",&pa[i].x,&pa[i].y);
        Graham(n,r);
        return 0;
    }
    View Code

     poj 1113  求上下凸包  求出整个凸包    排序+上凸包+下凸包

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    //#include<bits/stdc++.h>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.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); }
        Point operator -(const Point &b)const {     return Point(x-b.x,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));}
    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;                               } //点积
    const int maxn=1e3+10;
    Point pa[maxn],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]);
        ans+=pi*r*2;  printf("%.0f
    ",ans);
        return 0;
    }
    View Code

     半平面交  

    poj 3335 多边形求核  

    //#include<bits/stdc++.h>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    using namespace std;
    const double eps=1e-8;
    const double EPS=eps;
    const double pi=acos(-1.0);
    const double PI=pi;
    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){}
        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);}
    };
    struct Line{
        Point s,e;  // s-> 起始点  e->终点
        Line(){}
        Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
        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 get_angle(Point a){   return atan2(a.y,a.x);                 }// [-PI PI]
    double get_angle(Line a) {   return atan2(a.e.y-a.s.y,a.e.x-a.s.x); }
    bool judge(Point *pa,int n){  // 用多边形面积来判断正负
      double ans = 0;
      for (int i=1;i<n-1; i++) { ans+=((pa[i]-pa[0])^(pa[i+1]-pa[0])); }
      return ans>=0;
    }
    bool cmp(Line a,Line b){ // 极角排序  同极角左边就ok了
        Point va=a.e-a.s; double x=get_angle(va);
        Point vb=b.e-b.s; double y=get_angle(vb);
        if(fabs(x-y)<eps) { return (va^(b.e-a.s))>=0;   } // 射线的左右 注意和直线区别
        else return x<y;
    }
    bool onright(Line a,Line b,Line c){
        /*Point o=b&c;  // 判断 o 是否在a右边
        if( ((a.e-o)^(a.s-o))>0 ) return true;
        return false;*/
        Point o = b&c;
        if (((a.e - a.s) ^ (o - a.s)) < 0) return true;
        return false;
    }
    const int maxn=1e2+10;
    Point pa[maxn];
    Line que[maxn],la[maxn];
    bool HalfPlaneIntersection(Line *la,int n){
        sort(la,la+n,cmp);
        int head=0,tail=0,cnt=0;  // 栈模拟
        for (int i=0;i<n-1;i++) {
            if (fabs(get_angle(la[i])-get_angle(la[i+1]))<eps) {  // 去掉极角相同的(右边边的没用...)
              continue;
            }la[cnt++]=la[i];
        }la[cnt++]=la[n-1];
        for(int i=0;i<cnt;i++){
            //cout<<la[i].s.x<<" "<<la[i].s.y<<"->"<<la[i].e.x<<" "<<la[i].e.y<<endl;
            while(tail-head>1 && onright(la[i],que[tail-1],que[tail-2])) tail--;
            while(tail-head>1 && onright(la[i],que[head],que[head+1]))   head++;
            que[tail++]=la[i];
        }
        while(tail-head>1 && onright(que[head],que[tail-1],que[tail-2])) tail--;
        while(tail-head>1 && onright(que[tail-1],que[head],que[head+1]))   head++;
        if(tail-head<3) return false;
        return true;
    }
    int main(){
        int T; scanf("%d",&T);
        while(T--){
            int n; scanf("%d",&n);
            for(int i=0;i<n;i++){
                scanf("%lf %lf",&pa[i].x,&pa[i].y);
            }
            if(judge(pa,n)){ for(int i=0;i<n;i++)  la[i]=Line(pa[i],pa[(i+1)%n]);}
            else {           for(int i=0;i<n;i++)  la[i]=Line(pa[(i+1)%n],pa[i]);}
            //for(int i=0;i<n;i++){cout<<la[i].s.x<<" "<<la[i].s.y<<"->"<<la[i].e.x<<" "<<la[i].e.y<<endl;}
            //cout<<"---"<<endl;
            bool c=HalfPlaneIntersection(la,n);
            if(c) printf("YES
    ");
            else printf("NO
    ");
        }
    }
    View Code

     这个写法也OK  ONRIGHT

    bool onright(Line a,Line b,Line c){
        Point o=b&c;  // 判断 o 是否在a右边
        if( ((a.e-o)^(a.s-o))>0 ) return true;
        return false;
        /*Point o = b&c;
        if (((a.e - a.s) ^ (o - a.s)) < 0) return true;
        return false;*/
    }
    View Code

     大佬博客 和 代码   https://blog.csdn.net/qq_40861916/article/details/83541403

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    const int maxn = 1e3;
    const double EPS = 1e-5;
    int T, n;
    typedef struct Grid {
      double x, y;
      Grid(double a = 0, double b = 0) {x = a, y = b;}
    } Point, Vector;
    Vector operator - (Point a, Point b) {return Vector(b.x - a.x, b.y - a.y);}
    double operator ^ (Vector a, Vector b) {return a.x * b.y - a.y * b.x;}//叉乘
    struct Line {
      Point s, e;// s是重点
      Line() {}
      Line(Point a, Point b) {s = a, e = b;}
    };
    Point p[maxn];
    Line L[maxn], que[maxn];
    
    //得到极角角度
    double getAngle(Vector a) {
      return atan2(a.y, a.x);
    }
    
    //得到极角角度
    double getAngle(Line a) {
      return atan2(a.e.y - a.s.y, a.e.x - a.s.x);
    }
    
    //排序:极角小的排前面,极角相同时,最左边的排在最后面,以便去重
    bool cmp(Line a, Line b) {
      Vector va = a.e - a.s, vb = b.e - b.s;
      double A =  getAngle(va), B = getAngle(vb);
      if (fabs(A - B) < EPS) return ((va) ^ (b.e - a.s)) >= 0;
      return A < B;
    }
    
    //得到两直线相交的交点
    Point getIntersectPoint(Line a, Line b) {
      double a1 = a.s.y - a.e.y, b1 = a.e.x - a.s.x, c1 = a.s.x * a.e.y - a.e.x * a.s.y;
      double a2 = b.s.y - b.e.y, b2 = b.e.x - b.s.x, c2 = b.s.x * b.e.y - b.e.x * b.s.y;
      return Point((c1*b2-c2*b1)/(a2*b1-a1*b2), (a2*c1-a1*c2)/(a1*b2-a2*b1));
    }
    
    //判断 b,c 的交点是否在 a 的右边
    bool onRight(Line a, Line b, Line c) {
      Point o = getIntersectPoint(b, c);
      if (((a.e - a.s) ^ (o - a.s)) < 0) return true;
      return false;
    }
    
    bool HalfPlaneIntersection() {
      sort(L, L + n, cmp);//排序
      int head = 0, tail = 0, cnt = 0;//模拟双端队列
      //去重,极角相同时取最后一个。
      for (int i = 0; i < n - 1; i++) {
        if (fabs(getAngle(L[i]) - getAngle(L[i + 1])) < EPS) {
          continue;
        }
        L[cnt++] = L[i];
      }
      L[cnt++] = L[n - 1];
    
    
      for (int i = 0; i < cnt; i++) {
        //判断新加入直线产生的影响
        while(tail - head > 1 && onRight(L[i], que[tail - 1], que[tail - 2])) tail--;
        while(tail - head > 1 && onRight(L[i], que[head], que[head + 1])) head++;
        que[tail++] = L[i];
      }
      //最后判断最先加入的直线和最后的直线的影响
      while(tail - head > 1 && onRight(que[head], que[tail - 1], que[tail - 2])) tail--;
      while(tail - head > 1 && onRight(que[tail - 1], que[head], que[head + 1])) head++;
      if (tail - head < 3) return false;
      return true;
    }
    
    //判断输入点的顺序,如果面积 <0,说明输入的点为逆时针,否则为顺时针
    bool judge() {
      double ans = 0;
      for (int i = 1; i < n - 1; i++) {
        ans += ((p[i] - p[0]) ^ (p[i + 1] - p[0]));
      }
      return ans < 0;
    }
    
    int main()
    {
      scanf("%d", &T);
      while (T--) {
        scanf("%d", &n);
        for (int i = n - 1; i >= 0; i--) {
          scanf("%lf %lf", &p[i].x, &p[i].y);
        }
    
        if (judge()) {//判断输入顺序,保证逆时针连边。
          for (int i = 0; i < n; i++) {
            L[i] = Line(p[(i + 1)%n], p[i]);
          }
        } else {
          for (int i = 0; i < n; i++) {
            L[i] = Line(p[i], p[(i + 1)%n]);
          }
        }
        for(int i=0;i<n;i++){
            cout<<L[i].s.x<<" "<<L[i].s.y<<"==="<<L[i].e.x<<" "<<L[i].e.y<<endl;
        }
        if (HalfPlaneIntersection()) printf("YES
    ");
        else printf("NO
    ");
      }
    
      return 0;
    }
    View Code

     半平面交  三角形和长方形交  牛客2019国庆7

    //#include<bits/stdc++.h>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    using namespace std;
    const double eps=1e-12;
    const double EPS=eps;
    const double pi=acos(-1.0);
    const double PI=pi;
    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){}
        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);}
    };
    struct Line{
        Point s,e;  // s-> 起始点  e->终点
        Line(){}
        Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
        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;
        }
    };
    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 get_angle(Point a){   return atan2(a.y,a.x);                 }// [-PI PI]
    double get_angle(Line a) {   return atan2(a.e.y-a.s.y,a.e.x-a.s.x); }
    bool judge(Point *pa,int n){  // 用多边形面积来判断正负
      double ans = 0;
      for (int i=1;i<n-1; i++) { ans+=((pa[i]-pa[0])^(pa[i+1]-pa[0])); }
      return ans>=0;
    }
    bool cmp(Line a,Line b){ // 极角排序  同极角左边就ok了
        Point va=a.e-a.s; double x=get_angle(va);
        Point vb=b.e-b.s; double y=get_angle(vb);
        if(fabs(x-y)<eps) { return dcmp(va^(b.e-a.s))>=0;   } // 射线的左右 注意和直线区别
        else return x<y;
    }
    bool onright(Line a,Line b,Line c){
        /*Point o=b&c;  // 判断 o 是否在a右边
        if( ((a.e-o)^(a.s-o))>0 ) return true;
        return false;*/
        Point o = b&c;
        if (dcmp((a.e - a.s) ^ (o - a.s)) < 0) return true;
        return false;
    }
    const int maxn=50000+100;
    Point pa[maxn];
    Line que[maxn],la[maxn];
    double PolygonArea(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 area/2; // 可改
    }
    double HalfPlaneIntersection(Line *la,int n){
        sort(la,la+n,cmp);
        int head=0,tail=0,cnt=0;  // 栈模拟
        for (int i=0;i<n-1;i++) {
            if (fabs(get_angle(la[i])-get_angle(la[i+1]))<eps) {  // 去掉极角相同的(右边边的没用...)
              continue;
            }la[cnt++]=la[i];
        }la[cnt++]=la[n-1];
        for(int i=0;i<cnt;i++){
            while(tail-head>1 && onright(la[i],que[tail-1],que[tail-2])) tail--;
            while(tail-head>1 && onright(la[i],que[head],que[head+1]))   head++;
            que[tail++]=la[i];
        }
        while(tail-head>1 && onright(que[head],que[tail-1],que[tail-2])) tail--;
        while(tail-head>1 && onright(que[tail-1],que[head],que[head+1]))   head++;
        if(tail-head<3) return 0.00;
       // cout<<head<<" "<<tail<<endl;
        vector<Point> vs;
        for(int i=head;i<tail-1;i++){vs.push_back(que[i]&que[i+1]);}
        vs.push_back(que[tail-1]&que[head]);
        return PolygonArea(vs);
    }
    int main(){
        double x1,y1,x2,y2;
        double x3,y3,x4,y4;
        while(cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4){
            int n=0;
            Point a,b,c,d; a=Point(x1,y1); b=Point(x1,y2); c=Point(x2,y1);
            vector<Point> vs;  vs.push_back(a),vs.push_back(b); vs.push_back(c);
            if(PolygonArea(vs)>=0) {
                la[n++]=Line(a,b);
                la[n++]=Line(b,c);
                la[n++]=Line(c,a);
            }
            else {
                la[n++]=Line(b,a);
                la[n++]=Line(a,c);
                la[n++]=Line(c,b);
            }
            a=Point(x3,y3); b=Point(x3,y4); c=Point(x4,y4); d=Point(x4,y3);
            vs.clear();
            vs.push_back(a); vs.push_back(b); vs.push_back(c); vs.push_back(d);
            if(PolygonArea(vs)>=0) {
                la[n++]=Line(a,b);
                la[n++]=Line(b,c);
                la[n++]=Line(c,d);
                la[n++]=Line(d,a);
            }
            else {
                la[n++]=Line(b,a);
                la[n++]=Line(a,d);
                la[n++]=Line(d,c);
                la[n++]=Line(c,b);
            }
            printf("%.10f
    ",HalfPlaneIntersection(la,7));
        }
    }
    View Code

    旋转卡壳 

    poj 2187   凸包直径(两点间的最远距离)   (用int  避免double的误差)

    //#include<bits/stdc++.h>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    using namespace std;
    struct Point{
        int x,y;
        Point(){ x=0,y=0; }
        Point(int _x,int _y):x(_x),y(_y){}
        //void output(){ printf("%.2f %.2f
    ",x,y); }
        int operator ^(const Point &b)const{     return x*b.y-y*b.x;}//叉积
        int 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);}
    };
    struct Line{
        Point s,e;
        int A,B,C;
        Line(){}
        Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
        void change(){A=e.y-s.y;B=s.x-e.x;C=e.x*s.y-s.x*e.y; }
    };
    int dis(Point A,Point B)             {   return  (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);      }
    inline int cross(Point a,Point b)    {   return a.x*b.y-a.y*b.x;                               } //²æ»ý
    inline int dot(Point a,Point b)      {   return a.x*b.x+a.y*b.y;                               } //µã»ý
    bool up(Point a,Point b){ if(a.x!=b.x) return a.x<b.x; return a.y<b.y;  }
    const int maxn=50000+10;
    vector<Point> vs;
    Point pa[maxn],pt[maxn];
    void tubao(Point *pa,int n){  // 凸包求出来放在vs数组里; 有序(逆时针);
        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--;
        for(int i=1;i<=m;i++){  vs.push_back(pt[i]); }
    }
    int distance(Point pa,Line la){
        la.change();
        return abs(la.A*pa.x+la.B*pa.y+la.C);//  sqrt(la.A*la.A+la.B*la.B)
    }
    int tubao_distance(){
        if(vs.size()==0) return 0;
        if(vs.size()==1) return 0;
        if(vs.size()==2) return dis(vs[0],vs[1]);
        int p=0;
        int n=vs.size();
        int ans=0;
        for(int i=0;i<n;i++){
            Line lc=Line(vs[i],vs[(i+1)%n]);
            while(distance(vs[p],lc)<distance(vs[(p+1)%n],lc)|| distance(vs[p],lc)<distance(vs[((p-1)%n+n)%n],lc)){
                p++;  p=(p%n+n)%n;
            }
            ans=max(ans,dis(vs[i],vs[p]));
            ans=max(ans,dis(vs[(i+1)%n],vs[p]));
        }
        /*p=0;
        for(int i=0;i<n;i++){
            Line lc=Line(vs[i],vs[(i+1)%n]);
            while(dis(vs[p],vs[i])<dis(vs[(p+1)%n],vs[i])|| dis(vs[p],vs[i])<dis(vs[((p-1)%n+n)%n],vs[i])){
                p++;  p=(p%n+n)%n;
            }
            ans=max(ans,dis(vs[i],vs[p]));
            //ans=max(ans,dis(vs[(i+1)%n],vs[p]));
        }*/
        return ans;
    }
    int main(){
        int n; scanf("%d",&n);
        for(int i=0;i<n;i++){ scanf("%d %d",&pa[i].x,&pa[i].y);  }
        tubao(pa,n);
        int ans=tubao_distance();
        printf("%d
    ",ans);
    }
    View Code

     poj 2451 半平面交面积

    //#include<bits/stdc++.h>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    using namespace std;
    const double eps=1e-12;
    const double EPS=eps;
    const double pi=acos(-1.0);
    const double PI=pi;
    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){}
        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);}
    };
    struct Line{
        Point s,e;  // s-> 起始点  e->终点
        Line(){}
        Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
        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;
        }
    };
    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 get_angle(Point a){   return atan2(a.y,a.x);                 }// [-PI PI]
    double get_angle(Line a) {   return atan2(a.e.y-a.s.y,a.e.x-a.s.x); }
    bool judge(Point *pa,int n){  // 用多边形面积来判断正负
      double ans = 0;
      for (int i=1;i<n-1; i++) { ans+=((pa[i]-pa[0])^(pa[i+1]-pa[0])); }
      return ans>=0;
    }
    bool cmp(Line a,Line b){ // 极角排序  同极角左边就ok了
        Point va=a.e-a.s; double x=get_angle(va);
        Point vb=b.e-b.s; double y=get_angle(vb);
        if(fabs(x-y)<eps) { return dcmp(va^(b.e-a.s))>=0;   } // 射线的左右 注意和直线区别
        else return x<y;
    }
    bool onright(Line a,Line b,Line c){
        /*Point o=b&c;  // 判断 o 是否在a右边
        if( ((a.e-o)^(a.s-o))>0 ) return true;
        return false;*/
        Point o = b&c;
        if (dcmp((a.e - a.s) ^ (o - a.s)) < 0) rQeturn true;
        return false;
    }
    const int maxn=50000+100;
    Point pa[maxn];
    Line que[maxn],la[maxn];
    double PolygonArea(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 HalfPlaneIntersection(Line *la,int n){
        sort(la,la+n,cmp);
        int head=0,tail=0,cnt=0;  // 栈模拟
        for (int i=0;i<n-1;i++) {
            if (fabs(get_angle(la[i])-get_angle(la[i+1]))<eps) {  // 去掉极角相同的(右边边的没用...)
              continue;
            }la[cnt++]=la[i];
        }la[cnt++]=la[n-1];
        for(int i=0;i<cnt;i++){
            while(tail-head>1 && onright(la[i],que[tail-1],que[tail-2])) tail--;
            while(tail-head>1 && onright(la[i],que[head],que[head+1]))   head++;
            que[tail++]=la[i];
        }
        while(tail-head>1 && onright(que[head],que[tail-1],que[tail-2])) tail--;
        while(tail-head>1 && onright(que[tail-1],que[head],que[head+1]))   head++;
        if(tail-head<3) return 0.00;
        vector<Point> vs;
        for(int i=head;i<tail-1;i++){vs.push_back(que[i]&que[i+1]);}
        vs.push_back(que[tail-1]&que[head]);
        return PolygonArea(vs);
    }
    int main(){
        int n; scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%lf %lf %lf %lf",&la[i].s.x,&la[i].s.y,&la[i].e.x,&la[i].e.y);
        }
        double lim=10000;
        la[n++]=Line(Point(0,0),Point(lim,0));
        la[n++]=Line(Point(lim,0),Point(lim,lim));
        la[n++]=Line(Point(lim,lim),Point(0,lim));
        la[n++]=Line(Point(0,lim),Point(0,0));
        printf("%.1f
    ",HalfPlaneIntersection(la,n));
        return 0;
    }
    View Code
  • 相关阅读:
    计算机代数系统Computer Algebra Software: Mathematica, Maxima, Pari/GP
    计算机代数系统对比:Computer Algebra Software: Mathematica, Maxima, Pari/GP
    搜索大质数的算法PHP版本【算法导论实践】
    使用maxima解决初等数论中的问题:
    练习使用文法剖析工具:
    反查字符的unicode码~
    Maxima Overview:
    Elementary number theory using Maxima
    Word文档结构图内容“越界”问题:
    Maxima, Maple, and Mathematica: the Summary~
  • 原文地址:https://www.cnblogs.com/Andromeda-Galaxy/p/11676139.html
Copyright © 2011-2022 走看看