POJ 2826(巨恶心的几何题,不过这题还是很锻炼找错的能力的)
一开始的时候分析对了,不过老是WA。。。。。。唉,后来找了点测试数据,照我原来的想法应该是可以的装水的,不过输出却是0.00.。。。。
呃,好吧,慢慢找错。。
我就大致总结下,哪些地方有可能犯错:
1.2个线段共线的情况。
2.计算积水面积的时候不能只选择y小的那个,要考虑y如果相等的话呢。(我就是被这卡了)
3.在考虑一块木板是否被另一块挡住的时候,我是这样考虑的:如果2个线段y较大的点组成的线段,如果不严格跨立y轴,则肯定可以积水。。(排除2个线段中存在一个平行X轴,2线段共线,及其中一个线段的点在另一个线段上,也就是2个线段严格相交的情况,这里的线段是指题目开始给出的线段)。反之,选择在另一个线段下面的线段,比较下X绝对值。就能判断是否挡住了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<fstream> #define EPS 1e-13 using namespace std; struct point { int ix,iy; double dx,dy; point(){} point(double _dx, double _dy):dx(_dx),dy(_dy){} void ini() { dx = ix; dy = iy; } }fir[2],sec[2]; double cmp(double x) { if (x < 0)return -1; if (x > 0)return 1; return 0; } int cmp(int x) { if (x < 0)return -1; if (x > 0)return 1; return 0; } point max(const point &p, const point &q) { if (p.dy < q.dy) { return q; } else { return p; } } point min(const point &p, const point q) { if (p.dy < q.dy) { return p; } else { return q; } } double dcross(const point &p1, const point &p2, const point &q1, const point &q2) { return cmp((q2.dy - q1.dy)*(p2.dx - p1.dx) - (q2.dx - q1.dx)*(p2.dy - p1.dy)); } int icross(const point &p1, const point &p2, const point &q1, const point &q2) { return cmp((q2.iy - q1.iy)*(p2.ix - p1.ix) - (q2.ix - q1.ix)*(p2.iy - p1.iy)); } point intersection(const point &p, const point &q1, const point &q2) { return point((q1.dx - q2.dx)*(p.dy - q2.dy)/(q1.dy - q2.dy) + q2.dx, p.dy); } void get_line(const point &p, const point &q, double &k, double &b) { k = (q.dy - p.dy)/(q.dx - p.dx); b = q.dy - q.dx*k; } point get_point(const point &p1, const point &p2, const point &q1, const point &q2) //注意共线情况 { double k1,k2,b1,b2; if (p1.ix == p2.ix) { get_line(q1,q2,k1,b1); return point(p1.dx,p1.dx*k1+b1); } else { if (q1.ix == q2.ix) { get_line(p1,p2,k1,b1); return point(q1.dx,q1.dx*k1+b1); } else { get_line(p1,p2,k1,b1); get_line(q1,q2,k2,b2); return point((b2 - b1)/(k1 - k2),k1*(b2 - b1)/(k1 - k2) + b1); } } } bool on_seg(const point &p1, const point &p2, const point &q) { if (min(p1.ix,p2.ix) <= q.ix && q.ix <= max(p1.ix,p2.ix) && min(p1.iy,p2.iy) <= q.iy && q.iy <= max(p1.iy,p2.iy) && icross(p1,p2,p1,q) == 0) { return true; } return false; } bool intersect(const point &p1, const point &p2, const point &q1, const point &q2) { if (icross(p1,p2,p1,q1) == 0 && icross(p1,p2,p1,q2) == 0)return false; if (on_seg(p1,p2,q1) || on_seg(p1,p2,q2) || on_seg(q1,q2,p1) || on_seg(q1,q2,p2))return true; if (icross(p1,q1,p1,p2)*icross(p1,p2,p1,q2) > 0 && icross(q1,p1,q1,q2)*icross(q1,q2,q1,p2) > 0)return true; return false; } bool law() { if (fir[0].iy == sec[0].iy || fir[1].iy == sec[1].iy)return false; if (!intersect(fir[0],sec[0],fir[1],sec[1]))return false; point start = get_point(fir[0],sec[0],fir[1],sec[1]); for (int i(0); i<2; ++i) { fir[i].dx -= start.dx; fir[i].dy -= start.dy; sec[i].dx -= start.dx; sec[i].dy -= start.dy; } if (max(fir[1],sec[1]).dy < EPS && max(fir[1],sec[1]).dy > -EPS)return false; if (max(fir[0],sec[0]).dy < EPS && max(fir[0],sec[0]).dy > -EPS)return false; start.dx = start.dy = 0.00; point one(0,1); if (dcross(start, max(fir[0],sec[0]), start, one)*dcross(start, one, start, max(fir[1],sec[1])) > -EPS) { return true; } else { if (dcross(start,max(fir[0],sec[0]),start,max(fir[1],sec[1])) > EPS) { if (max(fir[1],sec[1]).dx > EPS && max(fir[0],sec[0]).dx > EPS && fabs(max(fir[1],sec[1]).dx) < fabs(max(fir[0],sec[0]).dx) - EPS){ return true; } else { if (max(fir[1],sec[1]).dx < -EPS && max(fir[0],sec[0]).dx < -EPS && fabs(max(fir[1],sec[1]).dx) > EPS + fabs(max(fir[0],sec[0]).dx)) { return true; } } } else { if (max(fir[1],sec[1]).dx < -EPS && max(fir[0],sec[0]).dx < -EPS && fabs(max(fir[1],sec[1]).dx) < fabs(max(fir[0],sec[0]).dx) - EPS) { return true; } else { if (max(fir[1],sec[1]).dx > EPS && max(fir[0],sec[0]).dx > EPS && fabs(max(fir[1],sec[1]).dx) > EPS + fabs(max(fir[0],sec[0]).dx)) { return true; } } } } return false; } int main() { int n; scanf("%d",&n); while (n--) { for (int i(0); i<2; ++i) { scanf("%d%d%d%d",&fir[i].ix,&fir[i].iy,&sec[i].ix,&sec[i].iy); fir[i].ini();sec[i].ini(); } if (law()) { point one = max(fir[0],sec[0]); point two = max(fir[1],sec[1]); point result; double ans; if (one.dy > two.dy) { result = intersection(two,fir[0],sec[0]); ans = fabs(result.dx - min(one,two).dx)*min(one,two).dy/2.0; } else { if (one.dy < two.dy) { result = intersection(one,fir[1],sec[1]); ans = fabs(result.dx - min(one,two).dx)*min(one,two).dy/2.0; } else { if (fabs(one.dx) > fabs(two.dx)) { ans = fabs(one.dx - two.dx)*two.dy/2.0; } else { ans = fabs(two.dx - one.dx)*one.dy/2.0; } } } printf("%.2lf\n",ans); } else { printf("0.00\n"); } } return 0; }