第十二届湖南省赛:三角形和矩形

Bobo 有一个三角形和一个矩形,他想求他们交的面积。
具体地,三角形和矩形由 8 个整数 x  1,y  1,x  2,y  2,x  3,y  3,x  4,y  4 描述。 表示三角形的顶点坐标是 (x  1,y  1),(x  1,y  2),(x  2,y  1), 矩形的顶点坐标是 (x  3,y  3),(x  3,y  4),(x  4,y 4),(x  4,y  3).
Input
输入包含不超过 30000 组数据。
每组数据的第一行包含 4 个整数 x  1,y  1,x  2,y  2 (x  1≠x  2,y  1≠y  2).
第二行包含 4 个整数 x  3,y  3,x  4,y  4 (x  3<x  4,y  3<y  4).
(0≤x  i,y  i≤10  4)
Output
对于每组数据,输出一个实数表示交的面积。绝对误差或相对误差小于 10  -6 即认为正确。
Sample Input
1 1 3 3
0 0 2 2
0 3 3 1
0 0 2 2
4462 1420 2060 2969
4159 257 8787 2970
Sample Output
1.00000000
0.75000000
439744.13967527

思路:用半平面交模版即可。注意初始向量的方向。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
struct Point
{
    double x,y;
}tri[4],rec[5],ch[10];
struct Line
{
    Point p;       //直线上任意一点
    Point v;      //直线方向向量
    double angle;  //极角
    Line(){}
    Line(Point p,Point v):p(p),v(v){angle=atan2(v.y,v.x);}
    bool operator<(const Line& L)const{return angle<L.angle;}
}L[10];
Point Vector(Point a,Point b)     //求向量a-b
{
	Point c;
	c.x=a.x-b.x;
	c.y=a.y-b.y;
	return c;
}
double cross(Point a,Point b)       //叉积
{
	return (a.x*b.y-a.y*b.x);
}
bool Onleft(Line L,Point p){return cross(L.v,Vector(p,L.p))>0;}  //点P在有向直线L的左边(线上不算)
Point Getinter(Line a,Line b)
{
    Point u=Vector(a.p,b.p);
    double t=cross(b.v,u)/cross(a.v,b.v);
    return (Point){a.p.x+a.v.x*t,a.p.y+a.v.y*t};
}
int Half(Line *L,int n,Point *poly)
{
    sort(L,L+n);
    int first,last;
    Point *p=new Point[n];
    Line *q=new Line[n];
    q[first=last=0]=L[0];
    for(int i=1;i<n;i++)
    {
        while(first<last&&!Onleft(L[i],p[last-1]))last--;
        while(first<last&&!Onleft(L[i],p[first]))first++;
        q[++last]=L[i];
        if(fabs(cross(q[last].v,q[last-1].v))<1e-7)
        {
            last--;
            if(Onleft(q[last],L[i].p))q[last]=L[i];
        }
        if(first<last)p[last-1]=Getinter(q[last-1],q[last]);
    }
    while(first<last&&!Onleft(q[first],p[last-1]))last--;  //删除无用面
    if(last-first<=1)return 0;      //空集
    p[last]=Getinter(q[last],q[first]);
    int m=0;
    for(int i=first;i<=last;i++)poly[m++]=p[i];
    return m;
}
double Polyarea(Point *p,int n)   //求多边形面积(任意形状都可)
{
	double area=0;
	for(int i=1;i<n-1;i++)
	{
		area+=cross(Vector(p[i],p[0]),Vector(p[i+1],p[0]));
	}
	return area/2;
}
int cmp1(const Point &x,const Point& y)
{
    if(x.x==y.x)return x.y<y.y;
    return x.x<y.x;
}
int cmp2(const Point &x,const Point& y)
{
    if(x.x==y.x)return x.y>y.y;
    return x.x<y.x;
}
int main()
{
    double x1,y1,x2,y2,x3,y3,x4,y4;
    while(scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2)!=EOF)
    {
        tri[0].x=x1,tri[0].y=y1;
        tri[1].x=x1,tri[1].y=y2;
        tri[2].x=x2,tri[2].y=y1;
        if(x2>x1)sort(tri,tri+3,cmp2);
        else sort(tri,tri+3,cmp1);         //让点按逆时针排序
        scanf("%lf%lf%lf%lf",&x3,&y3,&x4,&y4);
        rec[0].x=x3,rec[0].y=y3;
        rec[1].x=x4,rec[1].y=y3;
        rec[2].x=x4,rec[2].y=y4;
        rec[3].x=x3,rec[3].y=y4;
        int n=0;
        for(int i=0;i<3;i++)L[n++]=Line(tri[i],Vector(tri[(i+1)%3],tri[i]));
        for(int i=0;i<4;i++)L[n++]=Line(rec[i],Vector(rec[(i+1)%4],rec[i]));
        int m=Half(L,n,ch);
        printf("%0.8lf\n",Polyarea(ch,m));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值