bzoj 2618: [Cqoi2006]凸多边形 (半平面交)

2618: [Cqoi2006]凸多边形

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1195  Solved: 608
[ Submit][ Status][ Discuss]

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]内的整数




Source

[ Submit][ Status][ Discuss]

题解:半平面交

#include<iostream>  
#include<cstdio>  
#include<algorithm>  
#include<cstring>  
#include<cmath>  
#define  N 2000  
#define eps 1e-8  
#define inf 1e9  
using namespace std;  
struct vector {  
    double x,y;  
    vector (double X=0,double Y=0){  
        x=X,y=Y;  
    }  
}a[N],p[N],tmp[N];  
typedef vector point;  
vector operator -(vector a,vector b){  
    return vector (a.x-b.x,a.y-b.y);  
}  
vector operator +(vector a,vector b){  
    return vector (a.x+b.x,a.y+b.y);  
}  
vector operator *(vector a,double t){  
    return vector (a.x*t,a.y*t);  
}  
int n,m; 
int dcmp(double x){
	if (fabs(x)<eps) return 0;
	return x<0?-1:1;
} 
double cross(vector a,vector b)  
{  
    return a.x*b.y-a.y*b.x;  
}  
point glt(point a,point a1,point b,point b1)  
{  
    vector v=a1-a; vector w=b1-b;  
    vector u=a-b;  
    double t=cross(w,u)/cross(v,w);  
    return a+v*t;  
}  
void init()  
{  
   m=0;  
   p[m++]=point(inf,inf);  
   p[m++]=point(-inf,inf);  
   p[m++]=point(-inf,-inf);  
   p[m++]=point(inf,-inf);  
}  
void cut(point a,point b)  
{  
    int cnt=0;  
    memset(tmp,0,sizeof(tmp));  
    for (int i=0;i<m;i++){  
        double c=cross(b-a,p[i]-a);  
        double d=cross(b-a,p[(i+1)%m]-a);  
        if (dcmp(c)<=0) tmp[cnt++]=p[i];  
        if (dcmp(c)*dcmp(d)<0)   
         tmp[cnt++]=glt(a,b,p[i],p[(i+1)%m]);  
    }  
    m=cnt;  
    for (int i=0;i<cnt;i++) p[i]=tmp[i];  
}  
int main()  
{  
    freopen("a.in","r",stdin);  
    int T;  
    scanf("%d",&T);  
    init();
    for (int t=1;t<=T;t++) {
	    scanf("%d",&n);
	    for (int j=1;j<=n;j++) scanf("%lf%lf",&a[j].x,&a[j].y);
	    a[n+1]=a[1];
        for (int i=2;i<=n+1;i++)
            cut(a[i],a[i-1]);  
	}
    double area=0;  
    p[m]=p[0];  
    for (int i=1;i<m;i++)  
      area+=cross(p[i]-p[0],p[i+1]-p[0]);  
    printf("%.3lf\n",fabs(area)/2);   
}  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值