您的位置:首页 > 其它

POJ 2826 An Easy Problem?!

2013-08-29 10:34 323 查看
 

题目还行,可惜自己不争气。

一开始就想到了所有情况:

1. 两条线不相交,不能装水。

2. 两条线重合 或 平行 不能装水。

3. 其中一条线水平放置,不能装水。

4. 如下图, 不能装水,同理两直线都向右斜时,也有这种情况



4. 把3中的图稍微改动一下,就能装水了,如下图



可见,先判断是不是1,2,3 这几种情况,如果不是,那么4,5这两种情况要再判断一下。

 

我想,这次不能再看别人的解题报告, 要自己做才能学到许多,尽管自己的方法不是很好,

以下思路纯自己构思,代码纯手写, 写得太乱, 太杂, 尽管做了一下午,每次都是测试了好几组数据才交, 还是16WA,但完全靠自己A了心情就是不一样,爽啊。

通过这题我学会了思考,不要过分依赖别人,当然自己A了以后可以看看别人的做法,这个是很有必要的。

 

我的奇葩AC代码:




View Code

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define eps 10e-8

struct point
{
double x, y;
point(){}
point(double xx, double yy) : x(xx), y(yy){};
};

struct seg
{
point a, b;
seg(){}
seg(point aa, point bb) : a(aa), b(bb){};
}s[3];

point p, tmp;
int flag[3];

double cross(point o, point p1, point p2)//叉积
{
return (p1.x - o.x)*(p2.y - o.y) - (p1.y - o.y)*(p2.x - o.x);
}

bool seg_cross(seg s1, seg s2)//判断线段是否相交 (规范相交 和 不规范相交,不考虑共线)
{
if(cross(s1.a, s1.b, s2.a) * cross(s1.a, s1.b, s2.b) <= eps
&& cross(s2.a, s2.b, s1.a) * cross(s2.a, s2.b, s1.b) <= eps)
return 1;
return 0;
}
point line_cross(seg u,seg v) //两直线求交点(标准模板)
{
point ret=u.a;
double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))
/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
return ret;
}
bool judge(seg s1, seg s2)//判断两线段是否平行
{
if( (s1.a.y - s1.b.y)*(s2.a.x - s2.b.x) == (s2.a.y - s2.b.y)*(s1.a.x - s1.b.x) ) return 1;
return 0;
}
int main()
{
int cas, i, j;
scanf("%d", &cas);
while(cas--)
{
for(i = 1; i <= 2 ;i++)
scanf("%lf%lf%lf%lf",&s[i].a.x, &s[i].a.y, &s[i].b.x, &s[i].b.y);
if(!seg_cross(s[1], s[2]) || s[1].a.y == s[1].b.y || s[2].a.y == s[2].b.y ||judge(s[1], s[2])) //1,2这两种情况
{ printf("0.00\n"); continue;}
//求两线段交点,并去除交点以下的线段
p = line_cross(s[1], s[2]);
for(i = 1; i <= 2; i++)
{
if( s[i].a.y < s[i].b.y || s[i].a.y ==  s[i].b.y && s[i].a.x < s[i].b.x ) swap(s[i].a, s[i].b);  //把线段中 点y值大的移到 线段的a端点
s[i].b = p;    //b端变为交点
}
if(s[1].a.y > s[2].a.y )swap(s[1], s[2]); //把线段a端y值大的移到水线段s[1]去
if( (s[1].a.x - p.x) * (s[1].a.y - p.y) * (s[2].a.x - p.x) * (s[2].a.y - p.y) > -eps)//判断两直线斜率相乘是否大于0,除法和乘法正负性不变,就是4,5的情况和跟4,5对称的情况
{
if(seg_cross( seg( s[1].a, point(s[1].a.x, s[2].a.y) ), s[2])) //判断线段a端y值比较小的 线段 向上延长 跟 另一条线段是否相交,相交就说明 上面的板盖住了下面的板, 不能装水 。
{printf("0.00\n"); continue;}
}
// 剩下的情况都可以装水, 根据木桶效应,两个线段的高度应该取 两个之中最低的
if(s[1].a.y > s[2].a.y) s[1].a = line_cross( s[1], seg( point(0, s[2].a.y), point(1, s[2].a.y)) );
else if(s[1].a.y < s[2].a.y) s[2].a = line_cross( s[2], seg( point(0, s[1].a.y), point(1, s[1].a.y)) );
//计算面积
printf("%.2f\n", (s[1].a.y - p.y) * fabs((s[1].a.x - s[2].a.x))/2);

}
return 0;
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: