POJ 2826 An Easy Problem?!(计算几何)

An Easy Problem?!

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10533   Accepted: 1589

Description

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, x1y1x2y2x3y3x4y4.
(x1y1), (x2y2) are the endpoints of one board, and (x3y3), (x4y4) 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

Source

题意:就是两根木块组成一个槽,问槽里能装多少雨水。

题解:基本情况:不相交、相交、相交且覆盖(高的那块板挡住雨水入口)。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<vector>
#define N 100010
#define inf 99999999999.0

using namespace std;

struct Point {
    double x,y;
} ;

int n;

double multi(Point p0,Point p1,Point p2) {
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

bool is_inter(Point s1,Point e1,Point s2,Point e2) {
    return (max(s1.x,e1.x)>=min(s2.x,e2.x))&&
           (max(s2.x,e2.x)>=min(s1.x,e1.x))&&
           (max(s1.y,e1.y)>=min(s2.y,e2.y))&&
           (max(s2.y,e2.y)>=min(s1.y,e1.y))&&
           (multi(s1,s2,e1)*multi(s1,e1,e2)+1e-15>=0)&&
           (multi(s2,s1,e2)*multi(s2,e2,e1)+1e-15>=0);
}

Point jd(Point u1,Point u2,Point v1,Point v2) {
    Point ret=u1;
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
             /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    ret.x+=(u2.x-u1.x)*t;
    ret.y+=(u2.y-u1.y)*t;
    return ret;
}

int main() {
    //freopen("test.in","r",stdin);
    int  t;
    cin>>t;
    while(t--) {
        Point p[5];
        scanf("%lf%lf%lf%lf",&p[1].x,&p[1].y,&p[2].x,&p[2].y);
        scanf("%lf%lf%lf%lf",&p[3].x,&p[3].y,&p[4].x,&p[4].y);
        if(!is_inter(p[1],p[2],p[3],p[4])) {
            printf("0.00\n");
            continue;
        }
        Point it=jd(p[1],p[2],p[3],p[4]);
        Point a[3];
        int num=0;///高于交点it.y的点的个数
        for(int i=1; i<5; i++) {
            if(p[i].y>it.y) {
                num++;
                a[num]=p[i];
            }
        }
        //printf("num=%d\n",num);
        if(num<2) {
            printf("0.00\n");
            continue;
        }
        double ans=0;

        if(a[1].y>a[2].y) {///第一块板高于第二块板
            if(fabs(a[1].x-it.x)<1e-15) {
                ans=fabs(a[1].x-a[2].x)*fabs(it.y-a[2].y)/2;
            } else {
                double k=(a[1].y-it.y)/(a[1].x-it.x); ///a[1]->it的斜率
                double b=a[1].y-k*a[1].x;
                double x=(a[2].y-b)/k;     //a[1]->it上纵坐标为a[2].y的横坐标
                ans=fabs(a[2].y-it.y)*fabs(a[2].x-x)/2;
            }
            Point pp;
            pp.x=a[2].x;
            pp.y=1000000.0;
            if(is_inter(a[1],it,a[2],pp))///覆盖
                ans=0.0;
        } else {
            if(fabs(a[2].x-it.x)<1e-15) {
                ans=fabs(a[1].x-a[2].x)*fabs(it.y-a[1].y)/2;
            } else {
                double k=(a[2].y-it.y)/(a[2].x-it.x);
                double b=a[2].y-k*a[2].x;
                double x=(a[1].y-b)/k;
                ans=fabs(a[1].y-it.y)*fabs(a[1].x-x)/2;
            }
            Point pp;
            pp.x=a[1].x;
            pp.y=1000000.0;
            if(is_inter(a[2],it,a[1],pp))
                ans=0.0;
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

/*
9
6259 2664 8292 9080
1244 2972 9097 9680

0 1 1 0
1 0 2 1

0 1 2 1
1 0 1 2

0 0 10 10
0 0 9 8

0 0 10 10
0 0 8 9

0.9 3.1 4 0
0 3 2 2

0 0 0 2
0 0 -3 2

1 1 1 4
0 0 2 3

1 2 1 4
0 0 2 3

*/
/*
  6162.65
  1.00
  0.00
  0.00
  4.50
  0.50
  3.00
  0.75
  0.00
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-21 22:48:07

POJ 2826 An Easy Problem?!(计算几何)的相关文章

POJ 2826 An Easy Problem? 判断线段相交

POJ 2826 An Easy Problem?! -- 思路来自kuangbin博客 下面三种情况比较特殊,特别是第三种 G++怎么交都是WA,同样的代码C++A了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const double eps = 1e-8;

Poj 2826 An Easy Problem?!

地址:http://poj.org/problem?id=2826 题目: An Easy Problem?! Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13016   Accepted: 2003 Description It's raining outside. Farmer Johnson's bull Ben wants some rain to water his flowers. Ben nails tw

POJ 2826 An Easy Problem?!(计算几何)

基本就和网上题解一样的思路,把几种情况判掉blablabla..就WA了. 然后答案加个EPS就过了.显然这题没有写SPJ..卡了精度 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; struct Point { double x, y; Point() {} Point(double x, double y

POJ 2826 An Easy Problem?!(线段相交,分类讨论)

题意:给两个线段,问他们能收集到多少雨水. 链接:http://poj.org/problem?id=2826 解法:分四种情况讨论 1. 存在一个线段与x轴平行,答案为0 2. 两个线段没有交点,答案为0 3. 1和2都不满足时,令线段1为比较低的那个线段,且p1为其比较高的那个点,若该点往y轴正方向的射线与线段2有交点,则答案为0 4. 3不满足时,求出两线段交点x1,p1做一条平行于x轴的线,该线与线段2的交点x2,则三角形x1, x2, p1的面积就是答案 小结:此题属于分类讨论型的题,

POJ 2826 An Easy Problem!(简单数论)

Description Have you heard the fact "The base of every normal number system is 10" ? Of course, I am not talking about number systems like Stern Brockot Number System. This problem has nothing to do with this fact but may have some similarity. Y

POJ 2826 An Easy Problem?! 好题

题目大意就是两根木块组成一个槽,问槽里能装多少雨水,注意雨水垂直落下,思路也很简单,就是分类讨论有点糟. 1.如果两条线段不相交或者平行,则装0: 2.有一条平行x轴,装0: 3.若上面覆盖下面的,装0: 4.其它,叉积求面积. 直接上代码: #include <iostream> #include <cmath> #include <stdio.h> using namespace std; const double eps=1e-8; struct point{ d

简单几何(线段相交) POJ 2826 An Easy Problem?!

题目传送门 题意:两条线段看成两块木板,雨水从上方往下垂直落下,问能接受到的水的体积 分析:恶心的分类讨论题,考虑各种情况,尤其是入口被堵住的情况,我的方法是先判断最高的两个点是否在交点的同一侧,然后看看是否高的点覆盖了低的点,用叉积判断方向,其他的情况见网上的解释.貌似没有什么卡精度的数据.最后膜拜楼教主,难以望其项背... /************************************************ * Author :Running_Time * Created Ti

POJ 1152 An Easy Problem! (取模运算性质)

题目链接:POJ 1152 An Easy Problem! 题意:求一个N进制的数R,保证R能被(N-1)整除时最小的N. 第一反应是暴力.N的大小0到62.发现其中将N进制话成10进制时,数据会溢出.这里有个整除,即(N-1)取模为0. 例子:a1a2a3表示一个N进制的数R,化成10进制: (a1*N*N+a2*N+a3)%(N-1)==((a1*N*N)%(N-1)+(a2*N)%(N-1)+(a3)%(N-1))%(N-1)==(a1+a2+a3)%(N-1): 这样防止了数据的溢出.

[POJ] 2453 An Easy Problem [位运算]

An Easy Problem Description As we known, data stored in the computers is in binary form. The problem we discuss now is about the positive integers and its binary form. Given a positive integer I, you task is to find out an integer J, which is the min