zoukankan      html  css  js  c++  java
  • 算法复习——半平面交(bzoj2618凸多边形)

    讲解:

    这里套用wuvin神犇的ppt,附上友情链接:http://blog.leanote.com/wuvin

    半平面交:

    算法流程:

    注意事项:

    例题:

    Description

    逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
     

     

    则相交部分的面积为5.233。

    Input

    第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

    Output

        输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

    Sample Input

    2
    6
    -2 0
    -1 -2
    1 -2
    2 0
    1 2
    -1 2
    4
    0 -3
    1 -1
    2 2
    -1 0

    Sample Output

    5.233

    HINT

    100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

    题解:

      半平面交裸题

    心得:

      主要是代码很烦吧···一定要理清点与点之间的关系,多画图帮助理解;

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=250005;
    struct point 
    {
      double x;
      double y;
    }p[N],a[N];
    struct line
    {
      point a;
      point b;
      double slope;
    }l[N],q[N];
    inline double operator * (point a,point b)
    {
      return a.x*b.y-a.y*b.x;
    }
    inline point operator - (point a,point b)
    {
      point t;
      t.x=a.x-b.x;
      t.y=a.y-b.y;
      return t;
    }
    inline point inter(line a,line b)
    {
      double k1=(b.b-a.a)*(a.b-a.a);
      double k2=(a.b-a.a)*(b.a-a.a);
      double t=k1/(k1+k2);
      point k;
      k.x=b.b.x+(b.a.x-b.b.x)*t;
      k.y=b.b.y+(b.a.y-b.b.y)*t;
      return k;
    }
    bool jud(line a,line b,line c)
    {
      point t=inter(a,b);
      return (t-c.a)*(c.b-c.a)>0;
    }
    int n,k,cnt,tot;
    double ans;
    bool comp(line a,line b)
    {
      if(a.slope!=b.slope)  return a.slope<b.slope;
      else return (b.b-a.a)*(a.b-a.a)<0;
    }
    void build()
    {
      sort(l+1,l+cnt+1,comp);
      /*for(int i=1;i<=cnt;i++)
        cout<<l[i].a.x<<' '<<l[i].a.y<<' '<<l[i].b.x<<' '<<l[i].b.y<<endl;*/
      for(int i=1;i<=cnt;i++)
      {
        if(l[i].slope!=l[i-1].slope)tot++;
        l[tot]=l[i];
      } 
      int left=1,right=0; 
      q[++right]=l[1];
      q[++right]=l[2];
      cnt=tot,tot=0;
      for(int i=3;i<=cnt;i++)
      {
        while(left<right&&jud(q[right-1],q[right],l[i]))  right--;
        while(left<right&&jud(q[left+1],q[left],l[i]))  left++;
        q[++right]=l[i];
      }
      while(left<right&&jud(q[right-1],q[right],q[left]))  right--;
      while(left<right&&jud(q[left+1],q[left],q[right]))  left++;
      q[right+1]=q[left];
      for(int i=left;i<=right;i++)
        a[++tot]=inter(q[i],q[i+1]);
      
    }
    void getans()
    {
      if(tot<3)  return; 
      a[tot+1]=a[1];
      for(int i=1;i<=tot;i++)
        ans+=a[i]*a[i+1];
      ans=fabs(ans)/2;
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
      {
        scanf("%d",&k);
        for(int j=1;j<=k;j++)
          scanf("%lf%lf",&p[j].x,&p[j].y);
        p[k+1]=p[1];
        for(int j=1;j<=k;j++) 
        {
          l[++cnt].a=p[j];
          l[cnt].b=p[j+1];
        }
      }
      /*for(int i=1;i<=cnt;i++)
        cout<<l[i].a.x<<' '<<l[i].a.y<<' '<<l[i].b.x<<' '<<l[i].b.y<<endl;*/
      for(int i=1;i<=cnt;i++)
        l[i].slope=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
      build();
      getans();
      printf("%.3lf
    ",ans);
      return 0;
    }
     
  • 相关阅读:
    set
    网络流学习(最小费用最大流)
    网络流学习(最大流)
    模拟退火学习
    NOI Day1T1归程(Kruskal重构树+Dijkstra)
    线性基学习
    高斯消元学习
    manacher算法学习(求最长回文子串长度)
    AC自动机模板2
    AC自动机入门
  • 原文地址:https://www.cnblogs.com/AseanA/p/6615976.html
Copyright © 2011-2022 走看看