题目链接:点击打开链接
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11568 | Accepted: 1759 |
Description
Input
Output
Sample Input
2 0 1 1 0 1 0 2 1 0 1 2 1 1 0 1 2
Sample Output
1.00 0.00题意:两根木棍,摆放的方式由题目给出,问接到雨水的量是多少。(注意是平面,只要考虑面积)
思路:题目看似很简单,实际上却相当的恶心啊....说来惭愧,差点就1A了,就因为斜率偷懒了没用公式结果白WA了一个小时。
具体看代码吧,打了注释。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define eps 1e-8 struct Node { double x,y; }; double mulit(Node a,Node c,Node b)//向量ac与向量ab叉乘 { return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x); } Node get_point(Node a,Node b,Node c,Node d)//求直线ab与直线cd的交点(已证明线段与线段相交,则可以当做两直线) { Node ret=a; double t=((a.x-c.x)*(c.y-d.y)-(a.y-c.y)*(c.x-d.x)) /((a.x-b.x)*(c.y-d.y)-(a.y-b.y)*(c.x-d.x)); ret.x+=(b.x-a.x)*t; ret.y+=(b.y-a.y)*t; return ret; } int check(Node a,Node b,Node c,Node d) { if(mulit(a,c,b)*mulit(a,d,b)<eps&&mulit(c,a,d)*mulit(c,b,d)<eps)//注意这里必须要小于eps而不能<=0,不然会因为精度问题而出错 return 1; return 0; } int main() { int T; Node a,b,c,d; scanf("%d",&T); while(T--) { scanf("%lf %lf %lf %lf",&a.x,&a.y,&b.x,&b.y); scanf("%lf %lf %lf %lf",&c.x,&c.y,&d.x,&d.y); if(a.y==b.y||c.y==d.y)//有一根木棍是水平的,那么无论另外一根如何放置都不可能接到水了 { printf("0.00\n"); continue; } if(check(a,b,c,d))//检查线段是否相交 { Node point=get_point(a,b,c,d);//获得交点 Node r[10]; int top=0; if(a.y>point.y) r[top++]=a; if(b.y>point.y) r[top++]=b; if(c.y>point.y) r[top++]=c; if(d.y>point.y) r[top++]=d;//将在交点上面的点保存,因为交点下面的点无意义(该点与交点会形成一个斜向右下角或者左下角的板子,无法保存水) double sum; for(int j=0; j<top; j++)//遍历所有可行点 { for(int k=0; k<top; k++)//找到一个点在j点的左边且在j点的逆时针方向。左边是因为在j点右边或者和j点x坐标相等的点是无意义的,水从高处落下时会被上面的板子挡掉 if(r[k].x<r[j].x&&mulit(point,r[j],r[k])>0)//在j点的逆时针方向是因为如果找到的第二个板子在j点的顺时针方向,那同样会被j板子挡掉,无法保存 { Node p=r[k],q=r[j]; if(p.y<q.y)//p板子在q板子下面,则要在q和交点形成的直线上取一个高为p.y的点,因为只有等高才能装水 { if(q.x!=point.x)//如果q板子是垂直的话,x坐标不变 { double kk=(q.y-point.y)/(q.x-point.x);//直线q-point斜率 double l=point.y-kk*point.x;//y=ax+b的b q.x=(p.y-l)/kk;//知道y,求出x。x=(y-b)/k } q.y=p.y; } else if(p.y>q.y) { if(p.x!=point.x) { double kk=(p.y-point.y)/(p.x-point.x); double l=point.y-kk*point.x; p.x=(q.y-l)/kk; } p.y=q.y; } sum=mulit(point,q,p)/2;//接到水的区域一定是个三角形,因为是两个板子组成的 } } printf("%.2lf\n",sum); } else//线段不相交则无法接到水 printf("0.00\n"); } return 0; }