算法复习——半平面交(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\n",ans);
  return 0;
}

 

 

 

posted @ 2017-03-25 09:28  AseanA  阅读(379)  评论(0编辑  收藏  举报