An Easy Problem?!
Time Limit: 1000MS | Memory Limit: 65536K | |
Description
It's raining outside. Farmer Johnson's bull Ben wants some rain to water his flowers. Ben nails two wooden boards on the wall of his barn. Shown in the pictures below, the two boards on the wall just look like two segments on the plane, as they have the same width.
Your mission is to calculate how much rain these two boards can collect.
Your mission is to calculate how much rain these two boards can collect.
Input
The first line contains the number of test cases.
Each test case consists of 8 integers not exceeding 10,000 by absolute value, x 1, y 1, x 2, y 2, x 3, y 3, x 4, y 4. ( x 1, y 1), ( x 2, y 2) are the endpoints of one board, and ( x 3, y 3), ( x 4, y 4) are the endpoints of the other one.
Each test case consists of 8 integers not exceeding 10,000 by absolute value, x 1, y 1, x 2, y 2, x 3, y 3, x 4, y 4. ( x 1, y 1), ( x 2, y 2) are the endpoints of one board, and ( x 3, y 3), ( x 4, y 4) are the endpoints of the other one.
Output
For each test case output a single line containing a real number with precision up to two decimal places - the amount of rain collected.
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
题意:给你两块挡板的坐标,求能收集多少水。
题解:超级烦琐的计算几何题,我写这篇日志主要目的是把模板放上来23333.
言归正传,这题有很多坑。
1.答案要加eps
2.共线答案为0
3.平行答案为0
4.能收集水的三角形被挡住答案为0,比如0 0 10 10 0 0 8 9
5.判断相等与否必须用fabs(x-y)<eps
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; #define eps 1e-8 #define zero(x) (((x)>0?(x):-(x))<eps) struct point { double x; double y; }; int direction (point p0, point p1, point p2) { return ((p2.x - p0.x)*(p1.y - p0.y) - (p1.x - p0.x)*(p2.y - p0.y)); } bool on_segment (point p0, point p1, point p2) { int minx, maxx, miny, maxy; minx = min(p0.x, p1.x); maxx = max(p0.x, p1.x); miny = min(p0.y, p1.y); maxy = max(p0.y, p1.y); if (p2.x >= minx && p2.x <= maxx && p2.y >= miny && p2.y <= maxy) return true; else return false; } bool segments_intersect (point p1, point p2, point p3, point p4) { //判两条线段是否相交 int d1, d2, d3, d4; d1 = direction(p3, p4, p1); d2 = direction(p3, p4, p2); d3 = direction(p1, p2, p3); d4 = direction(p1, p2, p4); if (((d1 < 0 && d2 > 0) || (d1 > 0 && d2 < 0)) && ((d3 < 0 && d4 > 0) || (d3 > 0 && d4 < 0))) return true; else if (d1 == 0 && on_segment(p3, p4, p1)) return true; else if (d2 == 0 && on_segment(p3, p4, p2)) return true; else if (d3 == 0 && on_segment(p1, p2, p3)) return true; else if (d4 == 0 && on_segment(p1, p2, p4)) return true; else return false; } point intersection(point u1,point u2,point v1,point v2){//两条直线的交点 point ret=u1; double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x)) /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x)); ret.x+=(u2.x-u1.x)*t; ret.y+=(u2.y-u1.y)*t; return ret; } double xmult(point p1,point p2,point p0)//叉积 { return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } int dot_online_in(point p,point l1,point l2)//判断点是否在线段上 { return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps; } int main(){ int t; scanf("%d",&t); while(t--){ point a1,a2,a3,a4; scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a1.x,&a1.y,&a2.x,&a2.y,&a3.x,&a3.y,&a4.x,&a4.y); if(fabs(a1.x-a2.x)<eps&&fabs(a3.x-a4.x)<eps){//判两条线平行 斜率不存在 printf("0.00\n"); continue; } else if((fabs(a2.x-a1.x)>eps&&fabs(a3.x-a4.x)>eps)&&((fabs((a2.y-a1.y)/(a2.x-a1.x)-(a4.y-a3.y)/(a4.x-a3.x))<eps))){ printf("0.00\n");//判两条线平行 斜率存在 continue; } if(!segments_intersect(a1,a2,a3,a4)){//判是否有交点 printf("0.00\n"); continue; } point jiao=intersection(a1,a2,a3,a4);//两条直线的交点 double y=max(a1.y,a2.y); double yy=max(a3.y,a4.y); y=min(y,yy);//两块挡板的最低点 if(fabs(y-jiao.y)<eps){//判交点和最低点是否是同一点 printf("0.00\n"); continue; } point xx; xx.x=0; xx.y=y; point jiao1=intersection(xx,(point){xx.x+1,y},a1,a2);//封住三角形的上面的两个点的其中一个 point jiao2=intersection(xx,(point){xx.x+1,y},a3,a4);//第二个交点 point jiaoy2=intersection((point){jiao1.x,jiao1.y},(point){jiao1.x,jiao1.y+1},a3,a4);//做垂线 求出与另一条直线的交点 point jiaoy3=intersection((point){jiao2.x,jiao2.y},(point){jiao2.x,jiao2.y+1},a1,a2);//同理 if((jiao1.y<jiaoy2.y)&&(dot_online_in(jiaoy2,a3,a4))){/如果它上面有点且那个点在另一条线上 就代表挡住了 printf("0.00\n"); continue; } if((jiao2.y<jiaoy3.y)&&(dot_online_in(jiaoy3,a1,a2))){ printf("0.00\n"); continue; } printf("%.2f\n",fabs(jiao2.x-jiao1.x)*fabs(y-jiao.y)/2.0+eps); } return 0; }