csuoj1812: 三角形和矩形

1812: 三角形和矩形

Time Limit: 5 Sec   Memory Limit: 128 MB   Special Judge
Submit: 316   Solved: 155
[ Submit][ Status][ Web Board]

Description

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

HINT

Source

解题思路:求出三角形内包含的矩形的点矩形中包含的三角形的点以及三角形和矩形各个线段的交点这些点围成的多边形即为相交的面积

/* ***********************************************
Author       : ryc
Created Time : 2016-09-06 Tuesday
File Name    : E:\acm\csuoj\1812.cpp
Language     : c++
Copyright 2016 ryc All Rights Reserved
************************************************ */
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define eps 1e-8
using namespace std;
struct point{
    double x,y;
}S[5],J[5],I[110];
struct Node{
    point a,b;
}A[5];
int sig(double n){
    if(fabs(n)<eps)return 0;
    else if(n>eps)return 1;
    else return -1;
}
bool judge(int a,int b){//判断线段相交 
    if(min(A[a].a.x,A[a].b.x)>max(A[b].a.x,A[b].b.x)||min(A[a].a.y,A[a].b.y)>max(A[b].a.y,A[b].b.y)||min(A[b].a.x,A[b].b.x)>max(A[a].a.x,A[a].b.x)||min(A[b].a.y,A[b].b.y)>max(A[a].a.y,A[a].b.y))
    return false;
    double h,i,j,k;
    h=(A[a].b.x-A[a].a.x)*(A[b].a.y-A[a].a.y)-(A[a].b.y-A[a].a.y)*(A[b].a.x-A[a].a.x);
    i=(A[a].b.x-A[a].a.x)*(A[b].b.y-A[a].a.y)-(A[a].b.y-A[a].a.y)*(A[b].b.x-A[a].a.x);
    j=(A[b].b.x-A[b].a.x)*(A[a].a.y-A[b].a.y)-(A[b].b.y-A[b].a.y)*(A[a].a.x-A[b].a.x);
    k=(A[b].b.x-A[b].a.x)*(A[a].b.y-A[b].a.y)-(A[b].b.y-A[b].a.y)*(A[a].b.x-A[b].a.x);
    return h*i<=eps&&j*k<=eps;
}
void getinter(point p1,point p2,point p3,point p4,point &inter){//求交点 
    inter=p1;
    double ans=((p1.x-p3.x)*(p3.y-p4.y)-(p1.y-p3.y)*(p3.x-p4.x))/((p1.x-p2.x)*(p3.y-p4.y)-(p1.y-p2.y)*(p3.x-p4.x));
    inter.x+=(p2.x-p1.x)*ans;
    inter.y+=(p2.y-p1.y)*ans;
}
double dist(point p1,point p2){  
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));  
}  
double cp(point p1,point p2,point p3){  
    return (p3.x-p1.x)*(p2.y-p1.y)-(p3.y-p1.y)*(p2.x-p1.x);  
}
bool cmp(point a,point b){  
    double ans=cp(I[0],a,b);  
    if(sig(ans)==0){  
        return dist(I[0],a)-dist(I[0],b)<=0;  
    }  
    else return ans>0;  
}  
int main()
{
    double x1,y1,x2,y2,x3,y3,x4,y4;
    while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4)!=EOF){
        S[0].x=x1;S[0].y=y1;S[1].x=x1;S[1].y=y2;S[2].x=x2;S[2].y=y1;
        J[0].x=x3;J[0].y=y3;J[1].x=x3;J[1].y=y4;J[2].x=x4;J[2].y=y4;J[3].x=x4;J[3].y=y3;
        int cnt=0;
        for(int i=0;i<3;++i){//矩形中包含的三角形的点 
            if(S[i].x>=min(x3,x4)&&S[i].x<=max(x3,x4)&&S[i].y>=min(y3,y4)&&S[i].y<=max(y3,y4)){
                I[cnt].x=S[i].x;I[cnt].y=S[i].y;cnt++;
            }
        }
        for(int i=0;i<4;++i){//三角形中包含的矩形中的点 
            if(J[i].x>=min(x1,x2)&&J[i].x<=max(x1,x2)&&J[i].y>=min(y1,y2)&&J[i].y<=max(y1,y2)){
                double k=(y1-y2)/(x2-x1);double b=y1-k*x2;
                if((sig(k*x1-y1+b)>=0&&sig(J[i].x*k-J[i].y+b)>=0)||(sig(k*x1-y1+b)<=0&&sig(J[i].x*k-J[i].y+b)<=0)){
                    I[cnt].x=J[i].x;I[cnt].y=J[i].y;cnt++;
                }
            }
        }
        for(int i=0;i<3;++i){
            for(int j=0;j<4;++j){//求出三角形和矩形的线段的交点 
                A[0].a=S[i];A[0].b=S[(i+1)%3];A[1].a=J[j];A[1].b=J[(j+1)%4];
                //printf("%lf %lf %lf %lf\n",J[j].x,J[j].y,J[(j+1)%4].x,J[(j+1)%4].y);
                if(judge(0,1)){
                    if(A[0].a.x==A[0].b.x&&A[0].a.x==A[1].a.x&&A[1].a.x==A[1].b.x)continue;
                    if(A[0].a.y==A[0].b.y&&A[0].a.y==A[1].a.y&&A[1].a.y==A[1].b.y)continue;
                   //printf("%lf %lf %lf %lf %lf %lf %lf %lf\n",A[0].a.x,A[0].a.y,A[0].b.x,A[0].b.y,A[1].a.x,A[1].a.y,A[1].b.x,A[1].b.y);
                    getinter(A[0].a,A[0].b,A[1].a,A[1].b,I[cnt]);cnt++;
                   // printf("%lf %lf\n",I[cnt-1].x,I[cnt-1].y);
                }
            }
        }
       // printf("%d\n",cnt);
        if(cnt<2){
            printf("0.00000000\n");
        }
        else {
        	int pos=0; 
        	for(int i=0;i<cnt;++i){  
            	if(I[pos].y>=I[i].y){  
                	if(I[pos].y==I[i].y){  
                    	if(I[pos].x>I[i].x)pos=i;  
                	}  
                	else pos=i;  
            	}  
        	}  
        	point temp=I[pos];I[pos]=I[0];I[0]=temp; 
            sort(I+1,I+cnt,cmp);//极角排序 
            double ans=0;
            for(int i=0;i<cnt;++i){//求多边形面积 
                double area=(I[(i+1)%cnt].x*I[i].y-I[(i+1)%cnt].y*I[i].x)/2.0;
                ans+=area;
            }
            printf("%.9lf\n",fabs(ans));
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值