poj 2826

写了一句if(area<0) area=-area;并没毛用,WA一万年,照着discuss里面的说法试了一下printf(area+eps)就过了。。。

行行,以后计算几何题一律+eps输出,卧佛了

这题讨论还是很多了。

首先,我们要找出不会积水的情况

1.没有交点

2.两线段平行或重合

3.有一条线段垂直于地面和天

4.一根线段遮挡住了第二根线段,也就是遮挡住了朝天的开口。

然后,就可以求出朝天的开口的面积了,以较低的那个点作水平线交于另外一条线段,然后用叉积求面积

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 1e-8
using namespace std;

inline int sgn(double x)
{
	if(x<eps && x>-eps) return 0;
	if(x>0) return 1;
	else	return -1;
}

struct point
{
	double x,y;
	point(double a=0,double b=0)
	{
		x=a;y=b;
	}
	point operator + (const point &b)const
	{
		return point(x+b.x,y+b.y);
	}
	point operator - (const point &b)const
	{
		return point(x-b.x,y-b.y);
	}
	friend point operator * (double t,const point b)
	{
		return point(t*b.x,t*b.y);
	}
}p[10];
inline double dot(const point a,const point b)
{
	return a.x*b.x+a.y*b.y;
}
inline double det(const point a,const point b)
{
	return a.x*b.y-a.y*b.x;
}
struct line
{
	point s,e;
	double k;
	line(point a=point(),point b=point())
	{
		s=a;e=b;
	}
	
}a[5],L;
double area;
bool ans;

inline void prework()
{
	for(int i=1;i<=4;i++)
		scanf("%lf%lf",&p[i].x,&p[i].y);
	
}

inline bool point_on_seg(point &p,line &a)
{
	return sgn(det(p-a.s,p-a.e))==0 && sgn(dot(p-a.s,p-a.e))<=0;
}

inline bool parallel(line &l1,line &l2)
{
	return !sgn(det(l1.e-l1.s,l2.e-l2.s));
}

inline bool cross(line l1,line l2)
{
	line vec=line(l1.s,l1.e-l1.s);
	if(parallel(l1,l2))//覆盖的情况这里不行 
		return false; 
	if(det((l2.s-vec.s),vec.e)*det(vec.e,(l2.e-vec.s))<0-eps)
		return false;
	if(det((l2.s-l1.s),(l2.e-l1.s))*det((l2.s-l1.e),(l2.e-l1.e))>0+eps)
		return false;
	
	return true;
}

inline void seg_intersec(line l1,line l2,point &insec)
{
	point v=point(l1.e-l1.s),w=point(l2.e-l2.s);
	double t=det(l2.s-l1.s,w)/det(v,w);
	insec=l1.s+t*v;
}

inline void mainwork()
{
	if(p[1].y>p[2].y) swap(p[1],p[2]);
	if(p[3].y>p[4].y) swap(p[3],p[4]);
	ans=true;
	if(!cross(line(p[1],p[2]),line(p[3],p[4])))
		ans=false;
	if(sgn(p[1].y-p[2].y)==0 || sgn(p[3].y-p[4].y)==0)
		ans=false;
	double mxx,mxy;
	double k1=atan2(p[2].y-p[1].y,p[2].x-p[1].x);
	double k2=atan2(p[4].y-p[3].y,p[4].x-p[3].x);
	if(p[2].x<p[1].x && p[4].x<p[3].x)
	{
		if(p[2].x<p[4].x+eps && p[2].y>p[4].y && k1<k2)
			ans=false;
		if(p[4].x<p[2].x+eps && p[4].y>p[2].y && k2<k1)
			ans=false;
	}
	if(p[2].x>p[1].x && p[4].x>p[3].x)
	{
		if(p[2].x>p[4].x-eps && p[2].y>p[4].y && k1>k2)
			ans=false;
		if(p[4].x>p[2].x-eps && p[4].y>p[2].y && k2>k1)
			ans=false;
	}
	if(!ans)
		return;
	point insec,d2;
	double t;
	seg_intersec(line(p[1],p[2]),line(p[3],p[4]),insec); 
	if(p[2].y<p[4].y)
	{
		t=(p[2].y-p[3].y)/(p[4].y-p[3].y);
		d2=p[3]+(t*(p[4]-p[3]));
		area=det(point(p[2]-insec),point(d2-insec))/2;
	}
	else
	{
		t=(p[4].y-p[1].y)/(p[2].y-p[1].y);
		d2=p[1]+(t*(p[2]-p[1]));
		area=det(point(d2-insec),point(p[4]-insec))/2;
	}
	if(area<0.0)
		area=-area;
}

inline void print()
{
	if(ans)
		printf("%.2f\n",area+eps);
	else
		puts("0.00");
}

int main()
{
//	freopen("data.in","r",stdin);
//	freopen("my.out","w",stdout);
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}	
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值