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

一题很蛋疼的一题。目前为止还有一个问题我没搞清楚,问题注在代码中。

题目大意:

外面下雨了,农民Johnoson的bull(??是什么)Ben要接点雨水去浇花。Ben拿两个木板在墙上,如图所示,墙上的两块木板可以看作是空中的两条线段,它们有一定的宽度。

你的任务是计算两块木板能接多少水。

最后要计算两块木板能装水的部分的面积。但是要注意一种情况,雨是垂直往下滴的,如果装水的部分没有雨能够进去的话,也是接不到水的。如图:

这种情况下中间的部分虽然能装水,但是被上面的线段挡住了,雨也无法进入,这种情况下接水量是0。

思路分析:

首先排除几种情况:

1.两条线段如果不相交,则不可能产生存水的地方。

2.其中有一条线段是水平放置的,也不可能产生存水的地方。

3.如果两条线段在同一直线上,存水量也为0。

算法分析:

排除以上三种情况之后,存水量只与三点有关:线段的交点P,以及在P上面的点(y坐标大于P的y坐标的点)

设最高点为P0,次高点为P1。

过P1做竖直线和水平线,分别交P P0于点P2,P3。

图1,被挡住的情况下,P2的y坐标必介于P0和P1之间。

图2,P2的y坐标大于P0的y坐标。雨可以进入。

图3,P2 的y坐标小于P1的y坐标。

还有一种情况是没有交点。我的程序没有处理这种情况,但是也AC了。(出现这个情况的时候除数为0了,求出P2的坐标是(-1.#IND00,-1.#IND00)似乎表示无穷大?然后就不可能介于P0和P1之间了。。。)

最后如果是图1的情况输出0.00,否则计算三角形P,P1,P3的面积就是结果了。

附上代码:(纯C代码,略长。。。)

#include<stdio.h>
#include<math.h>
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
#define ABS(x) (((x)>0)?(x):(-(x)))
#define EPS 0.0000001/*精度控制*/
/*坐标的定义*/
typedef double coo;/*int*/
/*判相等*/
int is_equel(double a,double b)
{
double c=ABS(a-b);
if(c<=EPS) return ;/*相等*/
else return ;/*不相等*/
}
/*点、向量*/
typedef struct POINT
{
coo x,y;
}point,vector;
/*线段*/
typedef struct SEGMENT
{
point p1,p2;/*p[2];*/
}segment,line;
typedef struct LINE2/*一般式*/
{
coo A,B,C;
}line2;
/*向量的减法p1-p2*/
vector vector_minus(vector p1,vector p2)
{
vector p;
p.x=p1.x-p2.x;
p.y=p1.y-p2.y;
return p;
}
/*向量叉乘*/
double cross_product(vector p1,vector p2)
{/*x1y2-x2y1*/
return p1.x*p2.y-p1.y*p2.x;
}
int line_location(line l1,line l2)
{
if((l2.p2.y-l2.p1.y)*(l1.p2.x-l1.p1.x)==(l1.p2.y-l1.p1.y)*(l2.p2.x-l2.p1.x))
{
if((l2.p2.y-l1.p1.y)*(l1.p2.x-l1.p1.x)==(l1.p2.y-l1.p1.y)*(l2.p2.x-l1.p1.x))
return -;/*重合*/
else return ;/*平行*/
}
else return ;/*相交*/
} /*判断线段是否相交*/
int segment_intersect(segment l1,segment l2)
{
/*快速排斥试验*/
coo min,max;
min=MIN(l1.p1.x,l1.p2.x);
max=MAX(l2.p1.x,l2.p2.x);
if(min>max) return ;
min=MIN(l2.p1.x,l2.p2.x);
max=MAX(l1.p1.x,l1.p2.x);
if(min>max) return ;
min=MIN(l1.p1.y,l1.p2.y);
max=MAX(l2.p1.y,l2.p2.y);
if(min>max) return ;
min=MIN(l2.p1.y,l2.p2.y);
max=MAX(l1.p1.y,l1.p2.y);
if(min>max) return ;
/*跨立试验*/
if(cross_product(vector_minus(l1.p1,l2.p1),vector_minus(l2.p2,l2.p1))*cross_product(vector_minus(l1.p2,l2.p1),vector_minus(l2.p2,l2.p1))>) return ;
if(cross_product(vector_minus(l2.p1,l1.p1),vector_minus(l1.p2,l1.p1))*cross_product(vector_minus(l2.p2,l1.p1),vector_minus(l1.p2,l1.p1))>) return ;
return ;
}
line2 line_line2(line l)
{
line2 l2;
l2.A=l.p2.y-l.p1.y;
l2.B=l.p1.x-l.p2.x;
l2.C=l.p2.x*l.p1.y-l.p1.x*l.p2.y;
return l2;
}
/*直线相交的交点(两点式)*//*未处理平行和重合的情况*/
point line_intersection(line a,line b)
{
line2 l1,l2;
point i={,};
l1=line_line2(a);
l2=line_line2(b);
i.x= (l2.B*l1.C-l1.B*l2.C)/(l2.A*l1.B-l1.A*l2.B);
i.y=-(l2.A*l1.C-l1.A*l2.C)/(l2.A*l1.B-l1.A*l2.B);
return i;
}
void scan(line *l)
{
scanf("%lf%lf%lf%lf",&l->p1.x,&l->p1.y,&l->p2.x,&l->p2.y);
}
int main()
{
int t,i,j;
segment l1,l2;
point P,p2;
/*freopen("data.txt","r",stdin);
freopen("ouput2.txt","w",stdout);*/
scanf("%d",&t);
while(t--)
{
scan(&l1);
scan(&l2);
if(segment_intersect(l1,l2)==) printf("0.00\n");
else if(l1.p1.y==l1.p2.y||l2.p1.y==l2.p2.y) printf("0.00\n");
else if(line_location(l1,l2)!=) printf("0.00\n");
else
{
point p[];
P=line_intersection(l1,l2);
p[]=l1.p1;
p[]=l1.p2;
p[]=l2.p1;
p[]=l2.p2;
for(i=;i<;i++)
for(j=;j<i;j++)
{
if(p[i].y>p[j].y) {p2=p[i];p[i]=p[j];p[j]=p2;}
}
{
segment s1,s2,s0;/*| -*/
double S;
s0.p1=p[];s0.p2=P;
s1.p1=p[];s1.p2.x=p[].x;s1.p2.y=p[].y-;
s2.p1=p[];s2.p2.x=p[].x-;s2.p2.y=p[].y;
p[]=line_intersection(s1,s0);
if(p[].y<=p[].y&&p[].y>p[].y) printf("0.00\n");
else
{
p[]=line_intersection(s2,s0);
S=cross_product(vector_minus(p[],P),vector_minus(p[],P))/;
S=ABS(S);
printf("%.2lf\n",S+EPS);/*问题:为什么最后这里不加EPS就过不了呢???求大神解答。*/
}
}
}
}
return ;
}

不知道为什么调试过程中最后一步输出S之前已经取了绝对值,可是有次还是输出了-0.00。是什么情况???

【解题报告】PKU 2826 An Easy Problem?!的更多相关文章

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

    POJ 2826 An Easy Problem?! -- 思路来自kuangbin博客 下面三种情况比较特殊,特别是第三种 G++怎么交都是WA,同样的代码C++A了 #include <io ...

  2. POJ 2826 An Easy Problem?!

    An Easy Problem?! Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7837   Accepted: 1145 ...

  3. POJ 2826 An Easy Problem?![线段]

    An Easy Problem?! Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12970   Accepted: 199 ...

  4. POJ 2826 An Easy Problem?! 好的标题

    受该两块木板以形成槽的效果.Q槽可容纳雨水多,注意雨爆跌,思想是非常easy,分类讨论是有点差. 1.假定两条线段不相交或平行,然后再装0: 2.有一个平行x轴.连衣裙0. 3.若上面覆盖以下的,装0 ...

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

    Description Have you heard the fact "The base of every normal number system is 10" ? Of co ...

  6. POJ 2826 An Easy Problem?! --计算几何,叉积

    题意: 在墙上钉两块木板,问能装多少水.即两条线段所夹的中间开口向上的面积(到短板的水平线截止) 解法: 如图: 先看是否相交,不相交肯定不行,然后就要求出P与A,B / C,D中谁形成的向量是指向上 ...

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

    题目传送门 题意:两条线段看成两块木板,雨水从上方往下垂直落下,问能接受到的水的体积 分析:恶心的分类讨论题,考虑各种情况,尤其是入口被堵住的情况,我的方法是先判断最高的两个点是否在交点的同一侧,然后 ...

  8. POJ 2826 An Easy Problem?!(线段交点+简单计算)

    Description It's raining outside. Farmer Johnson's bull Ben wants some rain to water his flowers. Be ...

  9. 【百度之星2014~初赛(第二轮)解题报告】Chess

    声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载.可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...

随机推荐

  1. java基础知识回顾之final

    //继承弊端:打破了封装性. /* final关键字: 1,final是一个修饰符,可以修饰类,方法,变量. 2,final修饰的类不可以被继承. 3,final修饰的方法不可以被覆盖. 4,fina ...

  2. (转)两分钟彻底让你明白Android Activity生命周期(图文)!

    转自: http://blog.csdn.net/android_tutor/article/details/5772285 大家好,今天给大家详解一下Android中Activity的生命周期,我在 ...

  3. Struts2 直接返回字符串(可用于json)

    struts2可以在method中直接返回一个字符串而不是视图.让Action中的返回字符串的方法,直接return null;并在return之前用输出流输出字符串就可以了,跟servlet输出HT ...

  4. [转载]Jmeter那点事·ForEach和If控制器

    如果我们要实现一个循环,如果城市是北京,则返回首都:否则,返回城市.   一.新建用户自定义变量 添加-配置元件-用户自定义变量, 定义变量注意命名格式:变量名 加 下划线 加 数字(从1开始计数) ...

  5. 关于在linux下清屏的几种技巧

    在windows的DOS操作界面里面,清屏的命令是cls,那么在linux 里面的清屏命令是什么呢?下面笔者分享几种在linux下用过的清屏方法. 1.clear命令.这个命令将会刷新屏幕,本质上只是 ...

  6. 【poj3358】消因子+BSGS 或 消因子+欧拉定理 两种方法

    题意:给你一个分数,求它在二进制下的循环节的长度,还有第一个循环节从哪一位开始. For example, x = 1/10 = 0.0001100110011(00110011)w and 0001 ...

  7. CF A. Xenia and Divisors

    题目大意: n(为三的倍数)个数的一个序列(每个数均不大于7),找出a,b,c a能被b整除,b能被c整除,序列中的每个数都被用到. 1 2 3 4 5 6 7 只有 1 2 4 1 2 6 1 3 ...

  8. 安卓中bundle的使用

    Bundle类用作携带数据,它类似于Map,用于存放key-value形式的值,相对于Map,它提供了各种常用类型的putXxx()/getXxx()方法,Bundle的内部实际上是使用了HashMa ...

  9. QQ群共享文件下载很慢解决办法

    QQ群共享文件下载很慢解决办法.我们经常会不群里面共享文件,文件文件稍大,下载非常慢.家庭是20M的网速,一般正常下载能够达到2.5MB左右,而在QQ群实际下载网速却只有80KB左右.如果要下1G,就 ...

  10. 配置Linux系统网卡连接网络

    本实验需要两台虚拟机来完成,环境如下: 主机名称 操作系统 ip地址 本地主机 RHEL7_64 192.168.157.134 -> 192.168.129.127 远程主机 CentOS 6 ...