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{
    double x;
    double y;
};

struct line{
    point a;
    point b;
}l1,l2;

double ans;

//求叉积
double xmult(point p0 ,point p1 ,point p2){
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
 int dblcmp(double n){
    if(fabs(n)<eps) return 0;
    return n>0?1:-1;
 }
//判断是否相交,如何相交
int judge(line l1 ,line l2){
    double d1=dblcmp(max(l1.a.x,l1.b.x)-min(l2.a.x,l2.b.x));
    double d2=dblcmp(max(l2.a.x,l2.b.x)-min(l1.a.x,l1.b.x));
    double d3=dblcmp(max(l1.a.y,l1.b.y)-min(l2.a.y,l2.b.y));
    double d4=dblcmp(max(l2.a.y,l2.b.y)-min(l1.a.y,l1.b.y));
    double d5=dblcmp(xmult(l2.a,l1.a,l1.b));
    double d6=dblcmp(xmult(l2.b,l1.a,l1.b));
    double d7=dblcmp(xmult(l1.a,l2.a,l2.b));
    double d8=dblcmp(xmult(l1.b,l2.a,l2.b));
    if(d1>=0&&d2>=0&&d3>=0&&d4>=0){
        if(d5*d6>0||d7*d8>0) return 0;//不相交
        else if(d5==0&&d6==0) return 1;//共线相交
        else if(d5==0||d6==0||d7==0||d8==0) return 2;//端点相交
        else return 3;//规范相交
    }
    return 0;
}

//求斜率
bool getslope(line l ,double &k){
    double t=l.a.x-l.b.x;
    if(t==0) return false;
    k=(l.a.y-l.b.y)/t;
    return true;
}

//求线段交点
point getIntersect(line l1, line l2) {
    point p;
    double A1 = l1.b.y - l1.a.y;
    double B1 = l1.a.x - l1.b.x;
    double C1 = (l1.b.x - l1.a.x) * l1.a.y - (l1.b.y - l1.a.y) * l1.a.x;
    double A2 = l2.b.y - l2.a.y;
    double B2 = l2.a.x - l2.b.x;
    double C2 = (l2.b.x - l2.a.x) * l2.a.y - (l2.b.y - l2.a.y) * l2.a.x;
    p.x = (C2*B1 - C1*B2) / (A1*B2 - A2*B1);
    p.y = (C1*A2 - C2*A1) / (A1*B2 - A2*B1);
    if(p.x==-0) p.x=0;
    return p;
 }

 //求a,b两点中y坐标更大的点
 point getbiggerY(point a ,point b){
     point q;
     if (dblcmp(a.y-b.y) > 0) {
        q.x = a.x;
        q.y = a.y;
    } else {
        q.x = b.x;
        q.y = b.y;
    }
     return q;
 }

double getarea(point p ,point p1 ,point p2){
    point q;
    double a;
    if(dblcmp(p1.y-p2.y)>=0) {
        q.y = p2.y;
        q.x = p.x+(p1.x-p.x)*(p2.y-p.y) / (p1.y-p.y); //求另一点的坐标
        a=fabs(xmult(p, p2, q)) / 2; //叉积求面积
    }
    else {
        q.y = p1.y;
        q.x = p.x+(p2.x-p.x)*(p1.y-p.y) / (p2.y-p.y);
        a=fabs(xmult(p, p1, q)) / 2;
    }
    return a;
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        point p1 ,p2 ,p;
        cin>>l1.a.x>>l1.a.y>>l1.b.x>>l1.b.y;
        cin>>l2.a.x>>l2.a.y>>l2.b.x>>l2.b.y;
        if(judge(l1,l2)<=1)//是否相交
            {ans=0;cout<<0<<endl;}
        else{
            p1=getbiggerY(l1.a ,l1.b);//cout <<"("<<p1.x<<" "<<p1.y<<")"<<endl;
            p2=getbiggerY(l2.a ,l2.b);//cout <<"("<<p2.x<<" "<<p2.y<<")"<<endl;
            p=getIntersect(l1 ,l2); //cout <<"("<<p.x<<" "<<p.y<<")"<<endl;
            if(!dblcmp(p.x-p1.x)&&!dblcmp(p.y-p1.y) || !dblcmp(p.x-p2.x)&&!dblcmp(p.x-p2.y))//开口方向
               //{
                   ans=0;//cout<<1<<endl;}
            else{
                double k1 ,k2;
                bool f1 ,f2;
                f1 = getslope(l1, k1);
                f2 = getslope(l2, k2);
                if (!dblcmp(k1) || !dblcmp(k2))//{
                        ans = 0;//cout<<2<<endl;} //当有一条线段平行x轴时
                else if (f1 && f2) {//如果两条线都不与y轴平行
                    if (dblcmp(k1*k2) > 0) { //当两条线段的斜率符号相同时,
                        int d1 = dblcmp(k1-k2);
                        int d2 = dblcmp(k2);
                        if (d1>0&&d2>0&&dblcmp(p2.x-p1.x)*dblcmp(p2.x-p.x)<=0
                            || d1<0&&d2>0&&dblcmp(p1.x-p2.x)*dblcmp(p1.x-p.x)<= 0
                            || d1>0&&d2<0&&dblcmp(p1.x-p2.x)*dblcmp(p1.x-p.x)<= 0
                            || d1<0&&d2<0&&dblcmp(p2.x-p1.x)*dblcmp(p2.x-p.x)<= 0)//覆盖情况
                       // {
                            ans = 0;//cout<<3<<endl;}
                        else //{
                            ans=getarea(p,p1,p2);//cout<<4<<endl;}
                        }
                    else //{
                        ans=getarea(p,p1,p2);//cout<<5<<endl;}
                    }
                else //{
                        ans=getarea(p,p1,p2);//cout<<6<<endl;}
            }
        }
        printf ("%.2lf\n", ans);
    }
    return 0;
}
时间: 2024-10-13 01:42:05

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?!(计算几何)

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 bar

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?!(计算几何)

基本就和网上题解一样的思路,把几种情况判掉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?!

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