码迷,mamicode.com
首页 > 其他好文 > 详细

【POJ 2826】An Easy Problem?!(几何、线段)

时间:2016-07-31 01:40:48      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

两个木条装雨水能装多少。

两线段相交,且不遮盖的情况下才可能装到水。

求出交点,再取两线段的较高端点的较小值h,(h-交点的y)为三角形的高。

三角形的宽即为(h带入两条线段所在直线得到的横坐标的差值)。

三角形的面积即为雨水的量。

坑点:如果用G++提交,ans要加上eps才能过,c++提交则没问题。

#include <iostream>
#include <cmath>
#include <cstdio>
#define MAX 1<<31
#define dd double
using namespace std;
struct P {dd x,y;};
struct L{
	P s,e;
	void input(){
		scanf("%lf%lf%lf%lf",&s.x,&s.y,&e.x,&e.y);
		if(s.x>e.x)swap(s,e);
	}
	dd k(){//斜率
		if(s.x==e.x)return MAX;
		return (s.y-e.y)/(s.x-e.x);
	}
	dd highX(){//较高端点的x值
		if(s.y>e.y)return s.x;
		return e.x;
	}
}a,b;
dd xmult(P a,P b,P o){//叉积
	return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
bool isCross(L a,L b){//是否相交
	return xmult(a.s,a.e,b.s)*xmult(a.s,a.e,b.e)<=0;//取等号就包括端点在另一线段的情况
}
P getCross(L a,L b){
	P c;
	dd ka=a.k(),kb=b.k();
	if(ka==MAX){//a是竖直的
		c.x=a.s.x;
		c.y=(c.x-b.s.x)*kb+b.s.y;
	}
	else{
		if(kb==MAX)
			c.x=b.s.x;
		else
			c.x=(a.s.y-b.s.y-ka*a.s.x+kb*b.s.x)/(kb-ka);
		c.y=(c.x-a.s.x)*ka+a.s.y;
	}
	return c;
}
dd getx(L a,dd y){//a所在直线上纵坐标为y的点的x
	if(a.s.y==a.e.y)return a.s.x;
	return (y-a.s.y)*(a.s.x-a.e.x)/(a.s.y-a.e.y)+a.s.x;
}
bool shadow(L a,L b){//是否遮盖
	dd x1=a.highX(),x2=b.highX();
        //如果倾斜方向一样,k大的线段的较高端点的x也更大则遮盖了
//并且斜率相同的线段也会返回true return a.k()*b.k()>0&&(a.k()-b.k())*(x1-x2)>=0; } void solve(){ double ans=0; if(a.k()&&b.k()&&isCross(a,b)&&isCross(b,a)&&!shadow(a,b)){ P c=getCross(a,b); dd h=min(max(a.s.y,a.e.y),max(b.s.y,b.e.y)); dd w=fabs(getx(a,h)-getx(b,h)); ans=(h-c.y)*w/2.0; } printf("%.2f\n",ans); } int main() { int t; cin>>t; while(t--){ a.input(); b.input(); solve(); } }

【POJ 2826】An Easy Problem?!(几何、线段)

标签:

原文地址:http://www.cnblogs.com/flipped/p/5722170.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!