poj2462
看八戒在做这个题,我也做了做。。
坑很多,还是要注意细节。不得不吐槽,难道又到了计算几何只能套模板否则就一串WA的情况了么!
要不是八戒做出来了,这题我估计我也就扔到这里了。。哥不服啊~所以得做出来!
注意这个题,重复点、直线等关键词。还有,判断直线跟线段交点,需要先剪枝,就是判断这个线段端点跟直线端点叉乘是不是小于eps就行了。
#include <iostream>
#include <algorithm> #include <iomanip> #include <limits> using namespace std; #pragma warning(disable:4996) #define eps 1e-8 #define zero(x) (((x)>0?(x):-(x))<eps) struct point{ double x, y; }; struct line{ point a, b; }; bool cmp(point p1, point p2) { if (fabs(p1.x - p2.x) < eps) return p1.y < p2.y; return p1.x < p2.x; } 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); } point intersection(line u, line v) { point ret = u.a; double t = ((u.a.x - v.a.x)*(v.a.y - v.b.y) - (u.a.y - v.a.y)*(v.a.x - v.b.x)) / ((u.a.x - u.b.x)*(v.a.y - v.b.y) - (u.a.y - u.b.y)*(v.a.x - v.b.x)); ret.x += (u.b.x - u.a.x)*t; ret.y += (u.b.y - u.a.y)*t; return ret; } double dist(point a, point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } int inside_polygon(point q, int n, point* p, int offset_x, int offset_y, int on_edge = 2) { point q2; int i = 0, count; while (i < n) for (count = i = 0, q2.x = rand() + offset_x, q2.y = rand() + offset_y; i < n; i++) if (zero(xmult(q, p[i], p[(i + 1) % n])) && (p[i].x - q.x)*(p[(i + 1) % n].x - q.x) < eps && (p[i].y - q.y)*(p[(i + 1) % n].y - q.y) < eps) return on_edge; else if (zero(xmult(q, q2, p[i]))) break; else if (xmult(q, p[i], q2)*xmult(q, p[(i + 1) % n], q2) < -eps&&xmult(p[i], q, p[(i + 1) % n])*xmult(p[i], q2, p[(i + 1) % n]) < -eps) count++; return count & 1; } int main() { int num_of_point, num_of_line; while (cin >> num_of_point >> num_of_line && (num_of_point || num_of_line)) { point p[1005]; memset(p, 0, sizeof(p)); double Max_x = numeric_limits<double>::min(), Max_y = numeric_limits<double>::min(); for (int i = 0; i < num_of_point; i++) { cin >> p[i].x >> p[i].y; if (p[i].x > Max_x) Max_x = p[i].x; if (p[i].y > Max_y) Max_y = p[i].y; } p[num_of_point] = p[0];//pay attention it has add for one, in reality, the size of it...i've made a mistake here for (int i = 0; i < num_of_line; i++) { line temp; cin >> temp.a.x >> temp.a.y >> temp.b.x >> temp.b.y; point intersects[1005]; memset(intersects, 0, sizeof(intersects)); int count_of_intersects = 0; for (int i = 0; i < num_of_point; i++) { if (xmult((p[i]), temp.a, temp.b)*xmult(p[i + 1], temp.a, temp.b) < eps)//can the sigment and the line intersect? { if (fabs(xmult((p[i]), temp.a, temp.b)) < eps&&fabs(xmult(p[i + 1], temp.a, temp.b)) < eps)//"same point" continue; line a = { p[i], p[i + 1] }; point inter = intersection(a, temp); intersects[count_of_intersects++] = inter; } } sort(intersects, intersects + count_of_intersects, cmp); double ans = 0; for (int i = 0; i < count_of_intersects - 1; i++) { point center = { (intersects[i].x + intersects[i + 1].x) / 2, (intersects[i].y + intersects[i + 1].y) / 2 }; bool flag = inside_polygon(center, num_of_point + 1, p, (int)Max_x + 1, (int)Max_y + 1); if (flag == 1 || flag == 2) ans += dist(intersects[i], intersects[i + 1]); } cout << fixed << setprecision(3) << ans << endl; } } return 0; } |