湖南省第十二届大学生计算机程序设计竞赛 J 三角形和矩形 半平面交



链接:戳这里


1812: 三角形和矩形
Time Limit: 5 Sec  Memory Limit: 128 MB  Special Judge
[Submit][Status][Web Board]
Description
Bobo 有一个三角形和一个矩形,他想求他们交的面积。
具体地,三角形和矩形由 8 个整数 x1,y1,x2,y2,x3,y3,x4,y4 描述。 表示三角形的顶点坐标是 (x1,y1),(x1,y2),(x2,y1), 矩形的顶点坐标是 (x3,y3),(x3,y4),(x4,y4),(x4,y3).
Input
输入包含不超过 30000 组数据。
每组数据的第一行包含 4 个整数 x1,y1,x2,y2 (x1≠x2,y1≠y2).
第二行包含 4 个整数 x3,y3,x4,y4 (x3<x4,y3<y4).
(0≤xi,yi≤104)
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
HINT
Source
湖南省第十二届大学生计算机程序设计竞赛


思路:

半平面交板子题


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<iomanip>
#include<cmath>
#include<bitset>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
#define INF (1ll<<60)-1
#define Max 1e9
using namespace std;
struct point {
    long double x,y;
    point(long double x=0,long double y=0):x(x),y(y) {}
};
typedef point vec;
const long double eps=1e-8;
const long double pi=acos(-1.0);
bool cmp(point a,point b) {
    if(fabs(a.x-b.x)<=eps) return a.y<b.y;
    return a.x<b.x;
}
vec operator -(point a,point b) {
    return vec(a.x-b.x,a.y-b.y);
}
vec operator +(point a,point b) {
    return vec(a.x+b.x,a.y+b.y);
}
vec operator *(point a,long double t) {
    return vec(a.x*t,a.y*t);
}
vec operator /(point a,long double t) {
    return vec(a.x/t,a.y/t);
}
bool operator < (const point &a,const point &b) {
    return a.y<b.y || (fabs(a.y-b.y)<=eps && a.x<b.x);
}
bool operator == (const point &a,const point &b) {
    if(fabs(a.x-b.x)<=eps && fabs(a.y-b.y)<=eps)
        return true;
    return false;
}
int dcmp(long double x) {
    if(fabs(x)<=eps) return 0;
    return x<0?-1:1;
}
long double cross(vec a,vec b) {///叉积
    return a.x*b.y-a.y*b.x;
}
long double dot(vec a,vec b) {///点积
    return a.x*b.x+a.y*b.y;
}
long double disn(point a,point b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    /*两点之间的距离*/
}
struct line {
    point p;
    vec v;
    long double ang;
    line() {}
    line(point p,vec v):p(p),v(v) {
        ang=atan2(v.y,v.x);
    }
    point po(long double t) {
        return p+v*t;
    }
    bool operator < (const line &l) const {
        return ang<l.ang;
    }
};
bool onleft(line l,point p){///点在直线的左边 =0表示点不能在直线上
    return cross(l.v,p-l.p)>=0;
}
point GetLineIntersection(line a,line b){
    vec u=a.p-b.p;
    long double t=cross(b.v,u)/cross(a.v,b.v);
    return a.p+a.v*t;
    /*两条直线的交点*/
}
void convexhull(point *s,int &n) {
    sort(s,s+n,cmp);
    int m=0;
    point p[110];
    for(int i=0; i<n; i++) {
        while(m>1 && dcmp(cross(p[m-1]-p[m-2],s[i]-p[m-2]))<=0)
            m--;
        p[m++]=s[i];
    }
    int k=m;
    for(int i=n-2; i>=0; i--) {
        while(m>k && dcmp(cross(p[m-1]-p[m-2],s[i]-p[m-2]))<=0)
            m--;
        p[m++]=s[i];
    }
    m--;
    n=m;
    for(int i=0; i<n; i++) s[i]=p[i];
	/*建立凸包*/
}
vector<point> HalfplaneIntersection(vector<line> l) {
    int n=l.size();
    sort(l.begin(),l.end());
    int top=0,bot=0;
    vector<point> p(n);
    vector<line> q(n);
    vector<point> ans;
    q[0]=l[0];
    for(int i=0; i<n; i++) {
        while(bot<top && !onleft(l[i],p[top-1])) top--;
        while(bot<top && !onleft(l[i],p[bot])) bot++;
        q[++top]=l[i];
        if(dcmp(q[top].ang-q[top-1].ang)==0) {
            top--;
            if(onleft(q[top],l[i].p))
                q[top]=l[i];
        }
        if(bot<top) p[top-1]=GetLineIntersection(q[top-1],q[top]);
    }
    while(bot<top && !onleft(q[bot],p[top-1])) top--;
    if(top-bot<=1) return ans;
    p[top]=GetLineIntersection(q[top],q[bot]);
    for(int i=bot; i<=top; i++) {
        ans.push_back(p[i]);
    }
    return ans;
    /*半平面交 返回相交区域的点集*/
}
long double polyarea(vector<point> p){
    int num=p.size();
    long double area=0;
    for(int i=1;i<num-1;i++){
        area+=cross(p[i]-p[0],p[i+1]-p[0]);
    }
    return fabs(area*0.5);
    /*点集的面积
        p为点集  num为点的个数
    */
}
point s[10],p[10];
vector<line> L;
int main(){
    long double x1,y1,x2,y2,x3,y3,x4,y4;
    while(cin>>x1>>y1>>x2>>y2){
        cin>>x3>>y3>>x4>>y4;
        s[0].x=x1;s[0].y=y1;
        s[1].x=x1;s[1].y=y2;
        s[2].x=x2;s[2].y=y1;

        p[0].x=x3;p[0].y=y3;
        p[1].x=x3;p[1].y=y4;
        p[2].x=x4;p[2].y=y4;
        p[3].x=x4;p[3].y=y3;
        int n=3,m=4;
        convexhull(s,n);
        convexhull(p,m);
        s[n]=s[0];p[m]=p[0];
        L.clear();
        for(int i=0;i<n;i++) L.push_back(line(s[i],s[i+1]-s[i]));
        for(int i=0;i<m;i++) L.push_back(line(p[i],p[i+1]-p[i]));
        vector<point> poly=HalfplaneIntersection(L);
        //for(int i=0;i<n;i++) cout<<setprecision(20)<<poly[i].x<<" "<<poly[i].y<<endl;
        long double ans=polyarea(poly);
        cout<<setprecision(20)<<ans<<endl;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值