计算几何——An Easy Problem?! (多种情况讨论题)

题目链接:http://poj.org/problem?id=2826

It's raining outside. Farmer Johnson's bull Ben wants some rain to water his flowers. Ben nails two wooden boards on the wall of his barn. Shown in the pictures below, the two boards on the wall just look like two segments on the plane, as they have the same width.


Your mission is to calculate how much rain these two boards can collect.

Input

The first line contains the number of test cases.
Each test case consists of 8 integers not exceeding 10,000 by absolute value, x 1, y 1, x 2, y 2, x 3, y 3, x 4, y 4. ( x 1, y 1), ( x 2, y 2) are the endpoints of one board, and ( x 3, y 3), ( x 4, y 4) are the endpoints of the other one.

Output

For each test case output a single line containing a real number with precision up to two decimal places - the amount of rain collected.

Sample Input

2
0 1 1 0
1 0 2 1

0 1 2 1
1 0 1 2

Sample Output

1.00
0.00

七夕节快要来了,强神想要在下雨天收集一些雨水用来浇花,于是他在墙上钉了 两块木板。现在他想要计算出他能收集多少雨水,但是强神觉得这个问题太简单 了,所以他把这个问题交给了你们。并承诺得出答案的人可以从他那里领取一个 火把和一桶汽油。

Input

第一行T,表示有T组测试用例。

接下来每两行为一组数据,每行描述一个木板两端的坐标。

Output

每个样例输出一个数,表示能接到的雨水在墙上投影出的面积。

这是个恶心的多种情况讨论题,自身水平确实不够,做不出来,这里借鉴的网上的代码。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include <iomanip>
#include<cmath>
#include<float.h> 
#include<string.h>
#include<algorithm>
#define sf scanf
#define pf printf
#define mm(x,b) memset((x),(b),sizeof(x))
#include<queue>
#include<stack>
#include <iomanip>
#include<map>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
typedef long long ll;
const ll mod=1e9+100;
const double eps=1e-6;
const double pi=acos(-1.0);
const int inf=0xfffffff;
using namespace std;
const double EPS=1e-6;
struct point
{
    double x,y;
};
struct line
{
    point a,b;
};
bool judge(line n)
{
    if(n.a.y==n.b.y) return true;
    return false;
}
point operator -(point m,point n)
{
    point c;
    c.x=m.x-n.x;
    c.y=m.y-n.y;
    return c;
}
point operator +(point m,point n)
{
    point c;
    c.x=m.x+n.x;
    c.y=m.y+n.y;
    return c;
}
point operator * (point c,int t)
{
    point m;
    m.x=c.x*t;
    m.y=c.y*t;
    return m;
}
double operator /(point m,point n)
{
    return m.x *n.y-m.y*n.x;
}
bool cross(line n,line m)
{
    if(((n.a-m.a)/(m.b-m.a))*((n.b-m.a)/(m.b-m.a))<=0
       && ((m.a-n.a)/(n.b-n.a))*((m.b-n.a)/(n.b-n.a))<=0)
        return true;
    else return false;
}
point jiaop(line m,line n)
{
    point o;
    double t=fabs((n.a-m.a)/(n.b-m.a))/fabs((m.b-m.a)/(n.b-n.a));
    o=m.a;
    o.x+=(m.b.x-m.a.x)*t;
    o.y+=(m.b.y-m.a.y)*t;
    return o;
}
point maxp(line n)
{
    return n.a.y>n.b.y?n.a:n.b;
}
int main()
{
    int re;
    cin>>re;
    while(re--)
    {
        line m,n;
        cin>>m.a.x>>m.a.y>>m.b.x>>m.b.y;
        cin>>n.a.x>>n.a.y>>n.b.x>>n.b.y;
        if(judge(n)||judge(m)) 
        {   pf("0.00\n");continue;  }
        else if(!cross(m,n)) {  pf("0.00\n");continue;  }
        double k1=(m.b.y-m.a.y)/(m.b.x-m.a.x),k2=(n.b.y-n.a.y)/(n.b.x-n.a.x);
        if(k1==k2) {    pf("0.00\n");continue;  }
        point t,a,b;
        int num=0;
        t=jiaop(m,n);
        if(t.y<m.a.y) num++;if(t.y<m.b.y) num++;if(t.y<n.a.y) num++;if(t.y<n.b.y) num++;
        if(num<2)  {    pf("0.00\n");continue;  }
        if(k1*k2>0)//判断是否会覆盖 
        {
            if(k1>0)
            {
                if(k1>k2)
                {
                    if(max(m.a.x,m.b.x)>=max(n.a.x,n.b.x))
                    {
                        cout<<"0.00"<<endl;
                        continue;
                    }
                }
                else
                {
                    if(max(n.a.x,n.b.x)>=max(m.a.x,m.b.x))
                    {
                        cout<<"0.00"<<endl;
                        continue;
                    }
                }
            }
            else
            {
                if(k1<k2)
                {
                    if(min(m.a.x,m.b.x)<=min(n.a.x,n.b.x))
                    {
                        cout<<"0.00"<<endl;
                        continue;
                    }
                }
                else
                {
                    if(min(n.a.x,n.b.x)<=min(m.a.x,m.b.x))
                    {
                        cout<<"0.00"<<endl;
                        continue;
                    }
                }
            }
        }
        a=maxp(m);b=maxp(n);
        double ans;
        if(a.y>b.y)
        {
            if(fabs(a.x-t.x)<eps)
            ans=fabs(b.x-t.x)*(b.y-t.y)/2;
            else
            {
                double k=(a.y-t.y)/(a.x-t.x); ///a[1]->it的斜率
                double q=a.y-k*a.x;
                double x=(b.y-q)/k;     //a[1]->it上纵坐标为a[2].y的横坐标
                ans=fabs(b.y-t.y)*fabs(b.x-x)/2;
            }
        }else
        {
            if(fabs(b.x-t.x)<eps)
            ans=fabs(a.x-t.x)*(a.y-t.y)/2;
            else
            {
                double k=(b.y-t.y)/(b.x-t.x); ///a[1]->it的斜率
                double q=b.y-k*b.x;
                double x=(a.y-q)/k;     //a[1]->it上纵坐标为a[2].y的横坐标
                ans=fabs(a.y-t.y)*fabs(a.x-x)/2;
            }
        }
        pf("%.2lf\n",ans+EPS);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值