POJ 1279 Art Gallery

分析:题目就是让你求多边形的核的面积,多边形的核就相当于在某一点能看到所有顶点(不穿过边),这些点的集合就是多边形的核。

如果有不懂地方可以看我写的求两线段交点。

# include <stdio.h>
# include <math.h>
# define EPS 1e-8
  struct point
  {
      double x,y;
  };
  void Swap(point &a,point &b)//交换两点
  {
      point t;
      t=a; a=b; b=t;
  }
  double Cross(point a,point b,point c)//求ab ac向量的叉积
  {
      return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
  }
  double Area(point v[1505],int n)//求多边形的面积
  {
      int i;
      double ans=0;
      for(i=1;i<n;i++)
        ans+=Cross(v[1],v[i],v[i+1]);
      return ans/2;
  }
  void Equation(point p1,point p2,double &a,double &b,double &c)
  {//求过点p1,p2的直线ax+by+c=0
      a=p2.y-p1.y;
      b=p1.x-p2.x;
      c=p1.y*p2.x-p1.x*p2.y;
  }
  point Intersection(point p1,point p2,double a,double b,double c)
  {//求直线ax+by+c=0与点p1,p2的交点t
      double s1,s2;
      point t;
      s1=fabs(a*p1.x+b*p1.y+c);
      s2=fabs(a*p2.x+b*p2.y+c);
      t.x=(p1.x*s2+p2.x*s1)/(s1+s2);
      t.y=(p1.y*s2+p2.y*s1)/(s1+s2);
      return t;
  }
  void Cut(double a,double b,double c,point v[1505],int &m)
  {//直线ax+by+c=0切多边形v
      int i,t=0;
      point u[1505];
      for(i=1;i<=m;i++)
      {//如果点v在直线上或在直线的左侧(直线方向是按多边形逆时针方向)
          if(a*v[i].x+b*v[i].y+c<EPS)
            u[++t]=v[i];
          else
          {
              if(a*v[i-1].x+b*v[i-1].y+c<-EPS)
                u[++t]=Intersection(v[i-1],v[i],a,b,c);
              if(a*v[i+1].x+b*v[i+1].y+c<-EPS)
                u[++t]=Intersection(v[i],v[i+1],a,b,c);
          }
      }
      for(i=1;i<=t;i++)
        v[i]=u[i];
      v[0]=v[t]; v[t+1]=v[1]; m=t;
  }
  int main()
  {
      int i,j,t,n,m;
      double a,b,c;
      point v[1505],p[1505];
      scanf("%d",&t);
      while(t--)
      {
          scanf("%d",&n);
          for(i=1;i<=n;i++)
            scanf("%lf%lf",&v[i].x,&v[i].y);
          if(Area(v,n)<EPS)//如果给的点的顺序是顺时针,就改为逆时针
            for(i=1;i<=n/2;i++)
              Swap(v[i],v[n+1-i]);
          v[0]=v[n]; v[n+1]=v[1]; m=n;
          for(i=0;i<=n+1;i++)
            p[i]=v[i];
          for(i=1;i<=n;i++)
          {//对原图的每一条边按逆时针方向切割一边
              Equation(p[i],p[i+1],a,b,c);
              Cut(a,b,c,v,m);
          }
          printf("%.2f\n",Area(v,m));
      }
      return 0;
  }


你可能感兴趣的:(POJ 1279 Art Gallery)