hdu 2826(好坑,线段相交问题)

An Easy Problem?!

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 11576   Accepted: 1760

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, x1, y1, x2, y2, x3, y3, x4, y4. (x1, y1), (x2, y2) are the endpoints of one board, and (x3, y3), (x4, y4) 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
一点都不easy...

没能AC的看看吧。。

discuss里面参考数据:

9
样例一:
6259 2664 8292 9080 1244 2972 9097 9680
答案:6162.65

样例二:
0 1 1 0
1 0 2 1
答案:1.00

样例三:
0 1 2 1
1 0 1 2
答案:0.00

样例四:
0 0 10 10
0 0 9 8
答案:0.00

样例五:
0 0 10 10
0 0 8 9
答案:4.50

样例六: //这组数据其实我没过也AC了
0.9 3.1 4 0
0 3 2 2
答案:0.50

样例七:
0 0 0 2
0 0 -3 2
答案:3.00

样例八:
1 1 1 4
0 0 2 3
答案:0.75

样例九:
1 2 1 4
0 0 2 3
答案:0.00
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const double eps = 1e-8;
struct Point
{
    double x,y;
};
double cross(Point a,Point b,Point c)
{
    return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
///规范相交
bool isCross(Point a,Point b,Point c,Point d)
{
    if(cross(c,b,a)*cross(b,d,a)<-eps) return false; ///这里要改成eps我上面的那组数据才能为0.5..不过是0也能AC。。so strange
    if(cross(a,d,c)*cross(d,b,c)<-eps) return false;
    return true;
}
///计算两条直线的交点
Point intersection(Point a,Point b,Point c,Point d)
{
    Point p = a;
    double t = ((a.x-c.x)*(c.y-d.y)-(a.y-c.y)*(c.x-d.x))/((a.x-b.x)*(c.y-d.y)-(a.y-b.y)*(c.x-d.x));
    p.x +=(b.x-a.x)*t;
    p.y +=(b.y-a.y)*t;
    return p;
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--)
    {
        Point a,b,c,d;
        scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
        scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);
        if(a.y==b.y||c.y==d.y||!isCross(a,b,c,d))  ///排除水平放置还有不相交的情况
        {
            printf("0.00\n");
            continue;
        }
        Point p = intersection(a,b,c,d); ///交点
        double y = min(max(a.y,b.y),max(c.y,d.y));
        if(y<=p.y)  ///上面的y不可能小于交点,不然接不到水
        {
            printf("0.00\n");
            continue;
        }
        ///我只要y上面的点
        Point t1,t2;
        if(a.y>b.y) t1 = a;
        else t1 = b;
        if(c.y>d.y) t2 = c;
        else t2 = d;
        ///两个向量极角大的x坐标必定小于极角小的,不然雨水没办法流进去
        if(cross(t1,t2,p)>0&&t1.x>t2.x||cross(t2,t1,p)>0&&t2.x>t1.x)
        {
            double k,B,x,x0;
            if(y==t1.y)
            {
                x = t1.x;
                if(t2.x==p.x) ///这里略坑
                {
                    x0 = p.x;
                }
                else
                {
                    k = (t2.y- p.y)/(t2.x - p.x);
                    B = t2.y-k*t2.x;
                    x0 = (y-B)/k;
                }
            }
            else
            {
                x = t2.x;
                if(t1.x==p.x)
                {
                    x0 = p.x;
                }
                else
                {
                    k = (t1.y- p.y)/(t1.x - p.x);
                    B = t1.y-k*t1.x;
                    x0 = (y-B)/k;
                }

            }
            double l = fabs(x-x0);
            double h = fabs(y-p.y);
            printf("%.2lf\n",l*h/2);
            continue;
        }
        printf("0.00\n");
    }
    return 0;
}
时间: 2024-07-31 14:29:17

hdu 2826(好坑,线段相交问题)的相关文章

hdu 1086(判断线段相交)

传送门:You can Solve a Geometry Problem too 题意:给n条线段,判断相交的点数. 分析:判断线段相交模板题,快速排斥实验原理就是每条线段代表的向量和该线段的一个端点与 另一条线段的两个端点构成的两个向量求叉积,如果线段相交那么另一条线段两个端点必定在该线段的两边,则该线段代表的向量必定会顺时针转一遍逆时针转一遍,叉积必定会小于等于0,同样对另一条线段这样判断一次即可. #include <algorithm> #include <cstdio>

hdu 3304(直线与线段相交)

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12042   Accepted: 3808 Description Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments

HDU 1086 You can Solve a Geometry Problem too(判断线段相交)

题目地址:HDU 1086 就这么一道仅仅判断线段相交的题目写了2k多B的代码..是不是有点浪费...但是我觉得似乎哪里也优化不了了.... 判断线段相交就是利用的叉积.假如现在两条线段分别是L1和L2,先求L1和L2两个端点与L1的某个端点的向量的叉积,如果这两个的叉积的乘积小于0的话,说明L1在是在L2两个端点之间的,但此时并不保证一定相交.此时需要用同样的方法去判断L2是否在L1的两个端点之间,如果L2也在L1的两个端点之间的话,那就足以说明L1与L2相交.但是这题还需要判断是否端点也相交

hdu 1558 (线段相交+并查集) Segment set

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐标,当输入Q的时候输入n,然后输出与第n条线段相交的线段有多少条 首先判断线段是否相交,在算法导论p577上有介绍 线段A(x1,y1)-B(x2,y2),所在直线L1方程为F1(x,y)=0;线段C(x3,y3)-D(x4,y4),所在直线L2方程为F2(x,y)=0; 如何判断两条线段有交点:(

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;

HDU 3492 (直线与所有线段相交) Segment

题意: 给出n个线段,判断是否存在一条直线使得所有线段在直线上的射影的交非空. 分析: 如果我们找到一条与所有线段相交的直线,然后做一条与该直线垂直的直线,这些线段在直线上的射影就一定包含这个垂足. 所以我们只要判断是否存在一条直线与所有的点相交即可. 如果存在这样一条直线,那么将这条直线平移或者旋转,就会被这些线段中的某两个端点“卡”住. 所以我们枚举两个端点,然后判断这些线段是否与这两个点所在的直线都相交即可. 本以为是一道很简单的计算几何,结果卡了好几天. 看了别人的题解,才发现问题所在.

hdu 1558 线段相交+并查集

题意:要求相交的线段都要塞进同一个集合里 sol:并查集+判断线段相交即可.n很小所以n^2就可以水过 1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 int f[1010]; 8 char ch; 9 int tmp,n; 10 double X1,X2,Y1,Y2; 11 12 #def

hdu 4606 Occupy Cities(线段相交+最小路径覆盖+二分)

Occupy Cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1178    Accepted Submission(s): 388 Problem Description The Star Wars is coming to an end as the Apple Planet is beaten by the Ban

hdu1086(线段相交)

题目意思: 给出n个线段,判断这n条线段中,线段相交的对数. http://acm.hdu.edu.cn/showproblem.php?pid=1086 题目分析: 此题主要写出判断线段相交的函数,然后判断每一对线段即可,时间复杂度O(n*n).详细解释见代码. AC代码: /** *判断AB和CD两线段是否有交点: *同时满足两个条件:('x'表示叉积) * 1.C点D点分别在AB的两侧.(向量(ABxAC)*(ABxAD)<=0) * 2.A点和B点分别在CD两侧.(向量(CDxCA)*(