poj-2826 An Easy Problem?!

75 篇文章 0 订阅
30 篇文章 0 订阅

题意:

给出平面上的两条线段,现在有竖直下落的雨;

求这两条线段最多能接到多少雨;


题解:

听起来挺朴实的一道题,但是并不怎么好做,因为计算几何的实数。。

实际上可以把这道题分为两个步骤:判断水能不能进入容器,计算容器能装多少水;

第二步比较容易,我直接底乘高乱搞了;

主要是对接水的判断,这一步有一个挺正确的性质:

线段口的向量在较高边的向量和竖直向量中间的时候,接不到水;

然后直接上叉积判断一下就可以了;

具体可以照Discuss数据玩,那个还是很强的;


代码:


#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double EPS=1e-8;
const double INF=1e10;
struct Point
{
	double x,y;
	Point(){}
	Point(double _,double __):x(_),y(__){}
	friend Point operator +(Point a,Point b)
	{
		return Point(a.x+b.x,a.y+b.y);
	}
	friend Point operator -(Point a,Point b)
	{
		return Point(a.x-b.x,a.y-b.y);
	}
	friend double operator ^(Point a,Point b)
	{
		return a.x*b.y-a.y*b.x;
	}
	friend double operator *(Point a,Point b)
	{
		return a.x*b.x+a.y*b.y;
	}
	friend Point operator *(double a,Point b)
	{
		return Point(a*b.x,a*b.y);
	}
};
struct Line
{
	Point p,v;
	Line(){}
	Line(Point _,Point __):p(_),v(__){}
	void read()
	{
		Point temp;
		scanf("%lf%lf%lf%lf",&p.x,&p.y,&temp.x,&temp.y);
		if(p.y>temp.y)	swap(p,temp);
		v=temp-p;
	}
	Point operator [](int k)
	{
		if(k)	return p+v;
		else	return p;
	}
	friend bool Cross(Line a,Line b)
	{
		if((b.v^a[1]-b.p)*(b.v^a[0]-b.p)<EPS&&(a.v^b[1]-a.p)*(a.v^b[0]-a.p)<EPS&&fabs(a.v^b.v)>EPS)
			return 1;
		return 0;
	}
	friend Point getP(Line a,Line b)
	{
		Point u=a.p-b.p;
		double temp=(b.v^u)/(a.v^b.v);
		return a.p+temp*a.v;
	}
}l1,l2;
int main()
{
	int n,m,i,j,k;
	double ans;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		l1.read(),l2.read();
		if(Cross(l1,l2))
		{
			Point p=getP(l1,l2);
			if(l1[1].y<l2[1].y)
			{
				double height=l1[1].y-p.y;
				Point t1=l1[1];
				Point t2=getP(Line(t1,Point(1,0)),l2);
				Point V=l2[1]-t1;
				if((V^Point(0,1))*(V^l2.v)<EPS)
					ans=0;
				else
					ans=fabs(t1.x-t2.x)*height/2;
			}
			else
			{
				double height=l2[1].y-p.y;
				Point t1=l2[1];
				Point t2=getP(Line(t1,Point(1,0)),l1);
				Point V=l1[1]-t1;
				if((V^Point(0,1))*(V^l1.v)<EPS)
					ans=0;
				else
					ans=fabs(t1.x-t2.x)*height/2;
			}
		}
		else
			ans=0;
		printf("%.2lf\n",ans+EPS);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值