题目链接:Paint Erased
题目大意:
有两个操作,一个是把一个矩形区域染色,一个是把一个矩形区域的颜色抹掉。再给你一个折线,问折线有多长被涂了颜色。
操作数 1000, 折线有 最多100个点。
注:每个操作作用范围包含边界
解题思路:
将折线看做线段的累和,只要求出每一条线段的被染色长度,就能计算出总的被染色长度。
对于一条线段来说,倒着来看矩形操作:
1. 线段全部在矩形内部。如果矩形是操作是染色,就返回线段长度,否则返回0;
2. 线段平行坐标轴,线段垂直坐标轴,这么分的原因主要是:线段与矩形的边界重合,很恶心!!!
3. 就剩下斜着相交的部分了,特判特判特判。。。。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define db double
using namespace std;
const int N = 1005;
const int M = 105;
const db eps = 1e-8;
int sgn(db t)
{
return t < -eps ? -1 : t > eps;
}
struct P
{
db x, y;
P (db _x = 0, db _y = 0): x(_x), y(_y) {}
void input()
{
scanf("%lf%lf", &x, &y);
}
P operator - (const P &t) const
{
return P(x - t.x, y - t.y);
}
db len2()
{
return x * x + y * y;
}
db len()
{
return sqrt(len2());
}
bool operator == (const P &t) const
{
return sgn(x - t.x) == 0 && sgn(y - t.y) == 0;
}
bool operator < (const P &t) const
{
return x < t.x || (sgn(x - t.x) == 0 && y < t.y);
}
db operator ^ (const P &t) const
{
return x * t.y - t.x * y;
}
P operator * (const db &t) const
{
return P(x * t, y * t);
}
P operator + (const P &t) const
{
return P(x + t.x, y + t.y);
}
} p[M], c[5];
struct Rect
{
int ch;
P a, b;
void input()
{
scanf("%d", &ch);
a.input();
b.input();
}
bool in(const P &t) const
{
if(t.x > a.x - eps && t.x < b.x + eps && t.y > a.y - eps && t.y < b.y + eps) return true;
return false;
}
} r[N];
struct Line
{
P s, e;
Line() {}
Line(P _s, P _e)
{
s = _s;
e = _e;
}
P operator & (const Line &b) const
{
P res = s;
db t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return res;
}
};
bool inter(Line l1, Line l2)
{
return
max(l1.s.x, l1.e.x) >= min(l2.s.x, l2.e.x) &&
max(l2.s.x, l2.e.x) >= min(l1.s.x, l1.e.x) &&
max(l1.s.y, l1.e.y) >= min(l2.s.y, l2.e.y) &&
max(l2.s.y, l2.e.y) >= min(l1.s.y, l1.e.y) &&
sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) <= 0 &&
sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e-l2.e) ^ (l2.s - l2.e)) <= 0;
}
db dfs(P p1, P p2, int k)
{
if(k < 0) return 0.0;
bool ok1 = r[k].in(p1), ok2 = r[k].in(p2);
if(ok1 && ok2)
{
return (p1 - p2).len()*r[k].ch;
}
if(sgn(p1.x - p2.x) == 0)
{
if(p1.x > r[k].a.x - eps && p1.x < r[k].b.x + eps)
{
if(p1.y < p2.y) swap(p1, p2), swap(ok1, ok2);
if(p2.y > r[k].b.y - eps || p1.y < r[k].a.y + eps) return 0.0;
P u(p1.x, r[k].b.y), d(p1.x, r[k].a.y);
if(p1.y < r[k].b.y + eps) return (p1.y - r[k].a.y) * r[k].ch + dfs(d, p2, k - 1);
else if(p2.y > r[k].a.y - eps) return (r[k].b.y - p2.y) * r[k].ch + dfs(p1, u, k - 1);
else return dfs(p1, u, k - 1) + dfs(d, p2, k - 1) + (r[k].b.y - r[k].a.y) * r[k].ch;
}
else return 0.0;
}
if(sgn(p1.y - p2.y) == 0)
{
if(p1.y > r[k].a.y - eps && p1.y < r[k].b.y + eps)
{
if(p1.x > p2.x) swap(p1, p2), swap(ok1, ok2);
if(p2.x < r[k].a.x + eps || p1.x > r[k].b.x - eps) return 0.0;
P pl(r[k].a.x, p1.y), pr(r[k].b.x, p1.y);
if(p1.x > r[k].a.x - eps) return dfs(pr, p2, k - 1) + (r[k].b.x - p1.x) * r[k].ch;
else if(p2.x < r[k].b.x + eps) return dfs(p1, pl, k - 1) + (p2.x - r[k].a.x) * r[k].ch;
else return dfs(p1, pl, k - 1) + dfs(pr, p2, k - 1) + (r[k].b.x - r[k].a.x) * r[k].ch;
}
else return 0.0;
}
P c[5];
int lx(0);
c[lx++] = P(r[k].a.x, r[k].a.y);
c[lx++] = P(r[k].a.x, r[k].b.y);
c[lx++] = P(r[k].b.x, r[k].b.y);
c[lx++] = P(r[k].b.x, r[k].a.y);
c[4] = c[0];
P res[5];
int ln(0);
for(int j = 0; j < lx; j++)
{
Line l1(c[j], c[j + 1]), l2(p1, p2);
if(inter(l1, l2))
{
res[ln++] = l1 & l2;
}
}
sort(res, res + ln);
int cnt = unique(res, res + ln) - res;
if(cnt == 0) return dfs(p1, p2, k - 1);
if(!ok1 && ok2) swap(ok1, ok2), swap(p1, p2);
if(cnt == 1)
{
if(!ok2 && !ok1) return dfs(p1, p2, k - 1);
return dfs(p2, res[0], k - 1) + (p1 - res[0]).len() * r[k].ch;
}
if(p1.x > p2.x) swap(p1, p2);
return dfs(p1, res[0], k - 1) + dfs(res[1], p2, k - 1) + (res[1] - res[0]).len() * r[k].ch;
}
int main()
{
#ifdef PKWV
freopen("in.in", "r", stdin);
#endif
int n, m;
while(scanf("%d%d", &n, &m) + 1)
{
for(int i = 0; i < n; i++)
{
r[i].input();
}
for(int i = 0; i < m; i++)
p[i].input();
db s(0.0);
for(int i = 1; i < m; i++)
{
s += dfs(p[i - 1], p[i], n - 1);
}
printf("%.2f\n", s);
}
return 0;
}