什么毒瘤题,已经要调死了……
代码有注释,函数名应该挺友好的。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<double, double> PDD;
const int N = 1010, M = N * N * 2, INF = 2e9;
int h[N], e[M << 1], ne[M << 1], f[M << 1], idx = 1;
int cur[N], S, T;
int n, d[N], len, H;
void add(int a, int b, int c) {
e[ ++ idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx;
}
struct Line {
PDD a, b;
}AC, BD;
struct Circle {
double x, y, r;
};
struct Rectangle {
double x1, y1, x2, y2;
};
struct Graphics {
bool op;
Circle c;
Rectangle s;
}g[N];
struct Have_Intersection {
double dist(PDD a, PDD b) {
return (double)sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double dist(Line l, PDD p) { // 点 p 到直线 l 的距离
if (l.a.y == l.b.y) return fabs(p.y - l.a.y);
return fabs(p.x - l.a.x);
}
bool line(Line l, int k) { // 判断图形 k 与直线 l 之间是否有交点,默认直线是横线
if (!g[k].op) { // 圆与直线
auto &c = g[k].c;
if (dist(l, {c.x, c.y}) > c.r) return false;
return true;
}
else { // 矩形与直线
auto &s = g[k].s;
if ((l.a.x <= s.x1) && (l.b.x <= s.x1)) return false;
if ((l.a.x >= s.x2) && (l.b.x >= s.x2)) return false;
return (l.a.y >= s.y1) && (l.a.y <= s.y2);
}
}
bool graph(int a, int b) { // 判断图形 a 与图形 b 是否有交
if (g[a].op ^ g[b].op) { // 圆和矩形
if (g[a].op) swap(a, b);
auto &c = g[a].c;
auto &s = g[b].s;
PDD p[5] = {{s.x1, s.y1}, {s.x1, s.y2}, {s.x2, s.y1}, {s.x2, s.y2}};
for (int i = 0; i < 4; i ++ )
if (dist({c.x, c.y}, p[i]) <= c.r) return true;
for (int i = 0; i < 4; i ++ )
if (dist({p[i], p[(i + 1) % 4]}, {c.x, c.y}) <= c.r) return true;
return (c.x >= s.x1) && (c.x <= s.x2) && (c.y >= s.y1) && (c.y <= s.y2);
}
else if (!g[a].op) { // 圆和圆
return dist({g[a].c.x, g[a].c.y}, {g[b].c.x, g[b].c.y}) <= g[a].c.r + g[b].c.r;
}
else { // 矩形和矩形
PDD p[5] = {{g[a].s.x1, g[a].s.y1}, {g[a].s.x1, g[a].s.y2}, {g[a].s.x2, g[a].s.y1}, {g[a].s.x2, g[a].s.y2}};
for (int i = 0; i < 4; i ++ ) {
if (p[i].x >= g[b].s.x1 && p[i].x <= g[b].s.x2
&& p[i].y >= g[b].s.y1 && p[i].y <= g[b].s.y2)
return true;
}
swap(a, b);
PDD q[5] = {{g[a].s.x1, g[a].s.y1}, {g[a].s.x1, g[a].s.y2}, {g[a].s.x2, g[a].s.y1}, {g[a].s.x2, g[a].s.y2}};
for (int i = 0; i < 4; i ++ ) {
if (q[i].x >= g[b].s.x1 && q[i].x <= g[b].s.x2
&& q[i].y >= g[b].s.y1 && q[i].y <= g[b].s.y2)
return true;
}
return false;
}
}
}inter;
void Build_Graph() {
S = 0, T = n + n + 1;
for (int i = 1; i <= n; i ++ )
add(i, i + n, 1), add(i + n, i, 0);
for (int i = 1; i <= n; i ++ )
if (inter.line(BD, i))
add(S, i, INF), add(i, S, 0);
for (int i = 1; i <= n; i ++ )
if (inter.line(AC, i))
add(i + n, T, INF), add(T, i + n, 0);
for (int i = 1; i <= n; i ++ )
for (int j = i + 1; j <= n; j ++ )
if (inter.graph(i, j))
add(i + n, j, INF), add(j, i + n, 0),
add(j + n, i, INF), add(i, j + n, 0);
}
namespace Mini_Cut {
bool bfs() {
memset(d, -1, sizeof d);
queue<int> q;
q.push(S), d[S] = 0, cur[S] = h[S];
while (q.size()) {
int t = q.front();
q.pop();
for (int i = h[t]; i; i = ne[i]) {
int ver = e[i];
if (f[i] && d[ver] == -1) {
cur[ver] = h[ver];
d[ver] = d[t] + 1;
if (ver == T) return true;
q.push(ver);
}
}
}
return false;
}
int find(int u, int limit) {
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; i && flow < limit; i = ne[i]) {
cur[u] = i;
int ver = e[i];
if (d[ver] == d[u] + 1 && f[i]) {
int t = find(ver, min(limit - flow, f[i]));
if (!t) d[ver] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int dinic() {
int res = 0, flow;
while (bfs()) while (flow = find(S, INF)) res += flow;
return res;
}
}using namespace Mini_Cut;
int main() {
// INPUT
scanf("%d%d", &len, &H);
AC = {{0, H}, {len, H}};
BD = {{0, 0}, {len, 0}};
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
int op; double x, y, x2, y2, r;
scanf("%d", &op);
if (op == 1) {
scanf("%lf%lf%lf", &x, &y, &r);
g[i].op = 0, g[i].c = {x, y, r};
}
else {
scanf("%lf%lf%lf%lf", &x, &y, &x2, &y2);
g[i].op = 1, g[i].s = {x, y, x2, y2};
}
}
// WORK
Build_Graph();
printf("%d\n", dinic());
return 0;
}