计算几何 CSU1986 矩形相交问题

1986: 玄学

Submit Page    Summary    Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 96     Solved: 16    


Description

阴阳师子浩君,最近从《初等数论》,《线性代数》,《组合数学》三大玄学宝典中,取得了玄学的精髓,发现,当画出两个矩形组成的样子的图案时候,就很有可能出现SSR。 现在子浩君正研究《概率与统计》第四大宝典,所以,他需要统计这些图案的数据,子浩君有一项很重要的指标,就是该图形的面积,需要测量,但是,子浩君还需要研究宝典的精髓,所以这个任务就交给了作为一个ACMer的您,来帮他统计这项数据。
由于是要画符,如果最后组成的图案不能一笔画出,即两个矩形的边界一个公共点都没有的话,则输出不合法“Invalid!”。

Input

第一行为测试数据组数T(1<=T<=100)
第二行包括四个整数x1,y1,x2,y2,为第一个矩形某对角线两端端点的坐标。
第三行包括四个整数x3,y3,x4,y4,为第二个矩形某对角线两端端点的坐标。
矩形的每条边均和坐标轴平行。
输入保证其绝对值都在109范围以内,且保证输入的矩形不会退化为一个线段和一个点,即保证x1!=x2,y1!=y2,x3!=x4,y3!=y4。

Output

若两矩形相交,则输出矩形并的面积,若矩形的边界没有相交,则输出字符串“Invalid!”,不包括引号。

Sample Input

3

1 1 3 3
2 2 4 4

1 1 2 2
2 2 3 3

1 1 2 2
3 3 4 4

Sample Output

7
2
Invalid!

 

对于2条线段[x1x2][x3x4](x1<x2,x3<x4)

有相交条件:x1<=x4&&x2>=x3

 

对于两个矩形(对角线(x1,y1)(x2,y2)、(x3,y3)(x4,y4)(x1<x2,y1<y2;x3<x4,y3<y4)

可以分别投影到x轴与y轴,若x轴投影线、y轴投影分别均相交,那么矩形相交。

相交条件:min(x2,x4)>=max(x1,x3)&&min(y2,y4)>=max(x2,x4)

 

注:

本题中要求只要矩形边线不相交即输出invalid,也就是说包含情况也不算在内。

另外边界相交要单独判断,内包含边界相交时需要单独判断。

 

提前处理对角线并按照上面理论和注意事项编程即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

long long x1,x2,x3,x4,
          y11,y2,y3,y4;


void pre()
{
    if((x2-x1)*(y2-y11)<0) {
        if(x1>x2) swap(x1,x2);
        else swap(y11,y2);
    }
    if((x4-x3)*(y4-y3)<0){
        if(x3>x4) swap(x3,x4);
        else swap(y3,y4);
    }
    if(x1>x2){
        swap(x1,x2);swap(y11,y2);
    }
    if(x3>x4){
        swap(x3,x4);swap(y3,y4);
    }
//    if(x1>x3){
//        swap(x1,x3);swap(y1,y3);
//        swap(x2,x4);swap(y2,y4);
//    }
}

long long cal()
{
    long long dx=min(x2,x4)-max(x1,x3);
    long long dy=min(y2,y4)-max(y11,y3);
    long long s1=(x2-x1)*(y2-y11),s2=(x4-x3)*(y4-y3);
    //printf("s:%lld %lld\n",s1,s2);
    //printf("d:%lld %lld\n",dx,dy);
    if(dx>0&&dy>0){
        long long s=dx*dy;
        if((s==s1||s==s2)&&x1!=x3&&x2!=x4&&y11!=y3&&y2!=y4){
            return -1;
        }
        return s1+s2-s;
    }
    else if(dx==0&&dy>=0||dy==0&&dx>=0){
        return s1+s2;
    }
    return -1;
}

int main()
{
    int t;

    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld%lld%lld",&x1,&y11,&x2,&y2);
        scanf("%lld%lld%lld%lld",&x3,&y3,&x4,&y4);
        pre();
        long long ans=cal();
        if(ans==-1)
            printf("Invalid!\n");
        else
            printf("%lld\n",ans);

    }


    return 0;
}

/*
10
1 1 2 2 2 3 3 4

1 1 2 2 3 2 4 3

1 1 4 4 2 2 3 3

1 1 3 3 2 2 3 3

*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值