POJ 2826 An Easy Problem?!
题意:在平面上给两块板,求竖直落下的雨水能接多少
题解:巨恶心。。。有几个要特别注意的地方:
1.板平行-->0.00
2.一板盖住另一板-->0.00;
3.无交点-->0.00;'
4.能接水的模型:x型 、 v型、 Y型;
解决方法:
1.求的两线段的直线方程后直接判断a==0?
2.先求得有无交点,然后看交点的y,然后把两个最高的y找出来,这两个y不能小于交点y(就是交点必须是第三大的y)
然后判断 有第二大的y的那个线段对应x ,求另一条线段在x时的纵坐标,如果该值大于y且小于最大y,则为盖住
3.求接水量:找到矮点的木板,看它最大y对应另一木板(横切过去)的x值是多少,然后求(x1,y) (x2,y) (x0,y0) 构成的面积即可。
其中x1 x2 是 纵坐标为y时,两木板的x值,x0,y0为交点坐标。
代码:
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <queue> 7 #include <cmath> 8 using namespace std; 9 const double INF = 1E200; 10 const double eps = 1E-8; 11 struct POINT{ 12 double x,y; 13 POINT( double a = 0,double b = 0 ) { x = a; y = b; } 14 }; 15 POINT p[100+5]; 16 struct LINE // 直线的解析方程 a*x+b*y+c=0 为统一表示,约定 a >= 0 17 { 18 double a; 19 double b; 20 double c; 21 LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;} 22 }; 23 struct LINESEG{ 24 POINT e; 25 POINT s; 26 LINESEG( POINT x,POINT y ) { e = x; s = y; } 27 LINESEG(){} 28 }; 29 30 31 double dist(POINT p1,POINT p2) 32 { 33 return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) ); 34 } 35 double multiply(POINT sp,POINT ep,POINT op) 36 { 37 return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y)); 38 } 39 bool intersect(LINESEG u,LINESEG v) 40 { 41 return( (max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&& //排斥实验 42 (max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&& 43 (max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&& 44 (max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&& 45 (multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)>=0)&& //跨立实验 46 (multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0)); 47 } 48 //根据已知两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0 (a >= 0) 49 LINE makeline(POINT p1,POINT p2) 50 { 51 LINE tl; 52 int sign = 1; 53 tl.a=p2.y-p1.y; 54 if(tl.a<0) 55 { 56 sign = -1; 57 tl.a=sign*tl.a; 58 } 59 tl.b=sign*(p1.x-p2.x); 60 tl.c=sign*(p1.y*p2.x-p1.x*p2.y); 61 return tl; 62 } 63 bool lineintersect(LINE l1,LINE l2,POINT &p) // 是 L1,L2 64 { 65 double d=l1.a*l2.b-l2.a*l1.b; 66 if(abs(d)<eps) // 不相交 67 return false; 68 p.x = (l2.c*l1.b-l1.c*l2.b)/d; 69 p.y = (l2.a*l1.c-l1.a*l2.c)/d; 70 return true; 71 } 72 int main() 73 { 74 // freopen("out.txt","w",stdout); 75 int test; 76 cin>>test; 77 while(test--) 78 { 79 POINT p[5]; 80 int x[5],y[5]; 81 int flag = 0; 82 int idx1,idy1,idx2,idy2; 83 for(int i = 1;i <= 4; i++) cin>>x[i]>>y[i]; 84 LINESEG s1,s2; 85 s1.e.x = x[1];s1.e.y = y[1]; 86 s1.s.x = x[2];s1.s.y = y[2]; 87 s2.e.x = x[3];s2.e.y = y[3]; 88 s2.s.x = x[4];s2.s.y = y[4]; 89 if(!intersect(s1,s2)){puts("0.00");continue;} 90 LINE l1 = makeline(s1.e,s1.s); 91 LINE l2 = makeline(s2.e,s2.s); 92 if(l1.a == 0 || l2.a == 0){ puts("0.00");continue;} 93 lineintersect(l1,l2,p[0]); 94 idy1 = 1; 95 if(y[2]>y[1]) idy1 = 2; 96 idy2 = 3; 97 if(y[4]>y[3]) idy2 = 4; 98 if(y[idy1]>=y[idy2]) { p[1].x = x[idy1];p[1].y = y[idy1];p[2].x = x[idy2]; p[2].y = y[idy2]; } 99 else { p[1].x = x[idy2]; p[1].y = y[idy2]; p[2].x = x[idy1];p[2].y = y[idy1]; } 100 l1 = makeline(p[0],p[1]); 101 l2 = makeline(p[0],p[2]); 102 if(l1.b!=0){ 103 double yt = (-l1.c - l1.a*p[2].x)/l1.b; 104 if(yt - p[2].y>eps&&yt - p[1].y<eps&&yt-p[0].y>eps){ puts("0.00");continue;} 105 } 106 double xt = (- l1.c - l1.b*p[2].y)/l1.a; 107 POINT k; 108 k.x = xt; 109 k.y = p[2].y; 110 double s = multiply(p[2],p[0],k); 111 if(s<eps) s = -s; 112 printf("%.2f\n",s/2+eps); 113 } 114 }
浙公网安备 33010602011771号