基本模板
/* WXCU_ACM Yuxiao */
const double PI = acos(-1.0), eps = 1e-8;
int sign(double x) {
return fabs(x) < eps ? 0 : (x < 0) ? -1 : 1;
}
int dcmp(double x, double y) {
return sign(x - y);
}
double f(double x) {
return sin(x) / x;
}
double simpson(double l, double r) { // 求 f(x) 在l ~ r上的定积分
double mid = (l + r) / 2;
return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;
}
double asr(double l, double r, double s) { // 自适应辛普森积分
double mid = (l + r) / 2;
double left = simpson(l, mid), right = simpson(mid, r);
if (fabs(left + right - s) < eps) {
return left + right;
}
return asr(l, mid, left) + asr(mid, r, right);
}
/* 平面几何:点 线 */
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
Point operator+ (Point t) {
return Point(x + t.x, y + t.y);
}
Point operator- (Point t) {
return Point(x - t.x, y - t.y);
}
Point operator* (double k) {
return Point(x * k, y * k);
}
Point operator/ (double k) {
return Point(x / k, y / k);
}
bool operator== (Point t) {
return sign(x - t.x) == 0 && sign(y - t.y) == 0;
}
bool operator< (Point t) { // 用于凸包逆时针排序
return sign(x - t.x) < 0 || (sign(x - t.x) == 0 && sign(y - t.y) < 0);
}
};
typedef Point Vector;
double cross(Point a, Point b) {
return a.x * b.y - a.y * b.x;
}
double dot(Vector a, Vector b) { // 点积
return a.x * b.x + a.y * b.y;
}
double length(Vector a) { // 向量a的长度
return sqrt(dot(a, a));
}
double area(Point a, Point b, Point c) { // 叉积
return cross(b - a, c - a);
}
double angle(Vector a, Vector b) { // 两向量夹角
return acos(dot(a, b) / length(a) / length(b));
}
double distance(Point a, Point b) { // 两点距离
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
Point P_rotate(Point a, double k) { // 点a绕原点逆时针旋转k度
return {a.x * cos(k) + a.y * sin(k), -a.x * sin(k) + a.y * cos(k)};
}
Vector V_rotate(Vector a, double k) { // 向量a绕原点逆时针旋转k度
return {a.x * cos(k) - a.y * sin(k), a.x * sin(k) + a.y * cos(k)};
}
Vector normal(Vector a) { // 向量A的单位法向量
return {-a.y / length(a), a.x / length(a)};
}
bool parallel(Vector a, Vector b) { // 向量平行或重合
return sign(cross(a, b)) == 0;
}
struct Line {
Point x, y;
Line() {}
Line(Point x, Point y) : x(x), y(y) {}
// 根据一个点和倾角angle确定直线 0 <= angle <= PI
Line(Point p, double angle) {
x = p;
if (sign(angle - PI / 2) == 0) {
y = (x + Point(0, 1));
} else {
y = (x + Point(1, tan(angle)));
}
}
// ax + by + c = 0
Line(double a, double b, double c) {
if (sign(a) == 0) {
x = Point(0, -c / b);
y = Point(1, -c / b);
} else if (sign(b) == 0) {
x = Point(-c / a, 0);
y = Point(-c / a, 1);
} else {
x = Point(0, -c / b);
y = Point(1, (-c - a) / b);
}
}
};
typedef Line Segment;
double angle(Line a) { // 直线倾角
return atan2(a.y.y - a.x.y, a.y.x - a.x.x);
}
bool lcmp(Line a, Line b) { // 用于半平面交逆时针排序
double A = angle(a), B = angle(b);
if (!dcmp(A, B)) {
return area(a.x, a.y, b.y) < 0;
} else {
return A < B;
}
}
double PL_distance(Point p, Line a) { // 点到直线的距离
return fabs(cross(p - a.x, a.y - a.x)) / distance(a.x, a.y);
}
double PS_distance(Point p, Segment a) { // 点到线段的距离
if (sign(dot(p - a.x, a.y - a.x)) < 0 || sign(dot(p - a.y, a.x - a.y)) < 0) {
return min(distance(p, a.x), distance(p, a.y));
}
return PL_distance(p, a);
}
int PL_relation(Point p, Line a) { // 点和直线的关系:-1在左侧,0在直线上,1在右侧
int c = sign(cross(p - a.x, a.y - a.x));
return !c ? 0 : c < 0 ? -1 : 1;
}
int L_relation(Line a, Line b) { // 两直线关系:0平行,1重合,2相交
if (sign(cross(a.y - a.x, b.y - b.x)) == 0) {
return PL_relation(a.x, b) == 0 ? 1 : 0;
} else {
return 2;
}
}
bool PS_relation(Point p, Segment a) { // 点和线段的关系:0点p不在线段v上;1点p在线段v上
return sign(cross(p - a.x, a.y - a.x)) == 0 && sign(dot(p - a.x, p - a.y)) <= 0;
}
Point PL_project(Point p, Line a) { // 点在直线上的投影
double k = dot(a.y - a.x, p - a.x) / length(a.y - a.x) / length(a.y - a.x);
return a.x + (a.y - a.x) * k;
}
Point line_intersection(Point p, Point v, Point q, Point w) { // 两直线的交点
Point u = p - q;
double t = cross(w, u) / cross(v, w);
return p + v * t;
}
Point line_intersection(Line a, Line b) { // 两直线的交点
return line_intersection(a.x, a.y - a.x, b.x, b.y - b.x);
}
Line mid_line(Point a, Point b) { // 线段的中垂线
return {(a + b) / 2, V_rotate((b - a), PI / 2)};
}
/* 平面几何:圆*/
struct Circle {
Point c; double r;
Circle() {}
Circle(Point c, double r) : c(c), r(r) {}
Circle(double x, double y, double R) {
c = Point(x, y);
r = R;
}
};
Circle get_circle(Point a, Point b, Point c) { // 三点确定一条直线
Line u = mid_line(a, b), v = mid_line(a, c);
Point p = line_intersection(u.x, u.y, v.x, v.y);
return {p, distance(p, a)};
}
int PC_relation(Point p, Circle c) { // 点和圆的关系: 0点在圆内, 1点在圆上, 2点在圆外.
int d = sign(distance(p, c.c) - c.r);
return !d ? 0 : d < 0 ? -1 : 1;
}
int LC_relation(Line a, Circle c) { // 直线和圆的关系:0直线在圆内, 1直线和圆相切, 2直线在圆外
int d = sign(PL_distance(c.c, a) - c.r);
return !d ? 0 : d < 0 ? -1 : 1;
}
int SC_relation(Segment a, Circle c) { // 线段和圆的关系:0线段在圆内, 1线段和圆相切, 2线段在圆外
int d = sign(PS_distance(c.c, a) - c.r);
return !d ? 0 : d < 0 ? -1 : 1;
}
int LC_intersection(Line a, Circle c, Point &x, Point &y) { // 直线和圆的交点 x, y是交点 返回值是交点个数
if (LC_relation(a, c) == 2) {
return 0; // 无交点
}
Point q = PL_project(c.c, a);
double d = PL_distance(c.c, a);
double k = sqrt(c.r * c.r - d * d);
if (sign(k) == 0) { // 1个交点,直线和圆相切
x = q, y = q;
return 1;
}
Point n = (a.y - a.x) / length(a.y - a.x);
x = q + n * k, y = q - n * k;
return 2;
}
/* 平面几何:多边形*/
struct Polygon {
int n; // 多边形的定点数
Point p[N]; // 多边形的点
Line a[N]; // 多边形的边
};
int PP_relation(Point np, Polygon pg) { // 判断点和任意多边形的关系: 3点上; 2边上; 1内部; 0外部
auto p = pg.p;
auto n = pg.n;
for (int i = 0; i < n; i ++) { // 点在多边形的顶点上
if (p[i] == np) {
return 3;
}
}
for (int i = 0; i < n; i ++) { // 点在多边形的边上
Line a = Line(p[i], p[(i + 1) % n]);
if (PS_relation(np, a)) {
return 2;
}
}
int num = 0;
for (int i = 0; i < n; i ++) {
int j = (i + 1) % n;
int c = sign(cross(np - p[j], p[i] - p[j]));
int u = sign(p[i].y - np.y);
int v = sign(p[j].y - np.y);
if (c > 0 && u < 0 && v >= 0) {
num ++;
} else if (c < 0 && u >= 0 && v < 0) {
num --;
}
}
return num != 0; // 1内部,0外部
}
double Polygon_area(Polygon pg) { // 多边形面积
auto p = pg.p;
auto n = pg.n;
double res = 0;
for (int i = 0; i < n; i ++) {
res += cross(p[i], p[(i + 1) % n]);
}
return res / 2;
}
Point Polygon_center(Polygon pg) {
auto p = pg.p;
auto n = pg.n;
Point res = {0, 0};
if (Polygon_area(pg) == 0) {
return res;
}
for (int i = 0; i < n; i ++) {
res = res + (p[i] + p[(i + 1) % n]) * cross(p[i], p[(i + 1) % n]);
}
return res / Polygon_area(pg) / 6;
}
/* 立体(三维)几何:点 线*/
struct Point3 {
double x, y, z;
Point3() {}
Point3(double x, double y, double z) : x(x), y(x), z(z) {}
Point3 operator+ (Point3 t) {
return Point3(x + t.x, y + t.y, z + t.z);
}
Point3 operator- (Point3 t) {
return Point3(x - t.x, y - t.y, z - t.z);
}
Point3 operator* (double k) {
return Point3(x * k, y * k, z * k);
}
Point3 operator/ (double k) {
return Point3(x / k, y / k, z / k);
}
bool operator== (Point3 t) {
return sign(x - t.x) == 0 && sign(y - t.y) == 0 && sign(z - t.z) == 0;
}
};
typedef Point3 Vector3;
Vector3 cross(Point3 a, Point3 b) {
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
}
double dot(Vector3 a, Vector3 b) { // 点积
return a.x * b.x + a.y * b.y + a.z * b.z;
}
double length(Vector3 a) { // 向量a的长度
return sqrt(dot(a, a));
}
Vector3 area(Point3 a, Point3 b, Point3 c) { // 叉积
return cross(b - a, c - a);
}
double angle(Vector3 a, Vector3 b) { // 两向量夹角
return acos(dot(a, b) / length(a) / length(b));
}
double distance(Point3 a, Point3 b) { // 两点距离
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z));
}
struct Line3 {
Point3 x, y;
Line3() {}
Line3(Point3 x, Point3 y) : x(x), y(y) {}
};
typedef Line3 Segment3;
double PL_distance(Point3 p, Line3 a) { // 点到直线的距离
return length(cross(a.y - a.x, p - a.x)) / distance(a.x, a.y);
}
double PS_distance(Point3 p, Segment3 a) { // 点到线段的距离
if (sign(dot(p - a.x, a.y - a.x)) < 0 || sign(dot(p - a.y, a.x - a.y)) < 0) {
return min(distance(p, a.x), distance(p, a.y));
}
return PL_distance(p, a);
}
bool PL_relation(Point3 p, Line3 a) { // 点在直线上 0在,1不在
return sign(length(cross(a.x - p, a.y - p))) == 0 && sign(dot(a.x - p, a.y - p)) == 0;
}
Point3 PL_project(Point3 p, Line3 a) { // 点在直线上的投影
double k = dot(a.y - a.x, p - a.x) / length(a.y - a.x) / length(a.y - a.x);
return a.x + (a.y - a.x) * k;
}
andrew二维凸包
double andrew(int cnt) { // 二维凸包
sort(q, q + cnt);
cnt = unique(q, q + cnt) - q;
int top = 0;
for (int i = 0; i < cnt; i ++) {
while (top >= 2 && area(q[stk[top - 1]], q[stk[top]], q[i]) >= 0) {
st[stk[top --]] = false;
}
stk[++ top] = i;
st[i] = true;
}
st[0] = false;
for (int i = cnt - 1; i >= 0; i --) {
if (st[i]) {
continue;
}
while (top >= 2 && area(q[stk[top - 1]], q[stk[top]], q[i]) >= 0) {
top --;
}
stk[++ top] = i;
}
double res = 0;
for (int i = 2; i <= top; i ++) {
res += get_dist(q[stk[i - 1]], q[stk[i]]);
}
return res;
}
最小圆覆盖
random_shuffle(q, q + n); // 最小圆覆盖
Circle c = {q[0], 0};
for (int i = 1; i < n; i ++) {
if (dcmp(c.r, distance(c.c, q[i])) < 0) {
c = {q[i], 0};
for (int j = 0; j < i; j ++) {
if (dcmp(c.r, distance(c.c, q[j])) < 0) {
c = {(q[i] + q[j]) / 2, distance(q[i], q[j]) / 2};
for (int k = 0; k < j; k ++) {
if (dcmp(c.r, distance(c.c, q[k])) < 0) {
c = get_circle(q[i], q[j], q[k]);
}
}
}
}
}
}
圆的面积并
/*
Created by YuXiao
Nothing to say.
*/
#define YuXiao() cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <iomanip>
#define x first
#define y second
using namespace std;
typedef pair<double, double> PDD;
const int N = 1010;
const double eps = 1e-8, INF = 1e9;
int n;
PDD q[N];
vector<PDD> segs;
struct Circle
{
PDD r;
double R;
} c[N];
int dcmp(double x, double y)
{
if (fabs(x - y) < eps) return 0;
if (x < y) return -1;
return 1;
}
double f(double x)
{
int cnt = 0;
for (int i = 0; i < n; i ++)
{
auto X = fabs(x - c[i].r.x), R = c[i].R;
if (dcmp(X, R) < 0)
{
auto Y = sqrt(R * R - X * X);
q[cnt ++] = {c[i].r.y - Y, c[i].r.y + Y};
}
}
if (!cnt) return 0;
sort(q, q + cnt);
double res = 0, st = q[0].x, ed = q[0].y;
for (int i = 1; i < cnt; i ++)
if (q[i].x <= ed) ed = max(ed, q[i].y);
else
{
res += ed - st;
st = q[i].x, ed = q[i].y;
}
return res + ed - st;
}
double simpson(double l, double r)
{
auto mid = (l + r) / 2;
return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;
}
double asr(double l, double r, double s)
{
auto mid = (l + r) / 2;
auto left = simpson(l, mid), right = simpson(mid, r);
if (fabs(s - left - right) < eps) return left + right;
return asr(l, mid, left) + asr(mid, r, right);
}
void merge_range()
{
sort(segs.begin(), segs.end());
vector<PDD> new_segs;
double l = -INF, r = -INF;
for (auto &seg : segs)
{
if (dcmp(seg.x, r) <= 0) r = max(r, seg.y);
else
{
if (dcmp(l, -INF)) new_segs.push_back({l, r});
l = seg.x, r = seg.y;
}
}
new_segs.push_back({l, r});
segs = new_segs;
}
int main()
{
YuXiao();
cin >> n;
for (int i = 0; i < n; i ++)
{
cin >> c[i].r.x >> c[i].r.y >> c[i].R;
segs.push_back({c[i].r.x - c[i].R, c[i].r.x + c[i].R});
}
merge_range();
double res = 0;
for (auto &seg : segs) res += asr(seg.x, seg.y, simpson(seg.x, seg.y));
cout << fixed << setprecision(3) << res << endl;
return 0;
}
扫描线
/*
Created by YuXiao
Nothing to say.
*/
#define YuXiao() cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 1010;
int n;
PII l[N], r[N];
PII q[N];
vector<int> xs;
LL range_area(int a, int b)
{
int cnt = 0;
for (int i = 0; i < n; i ++)
if (l[i].x <= a && r[i].x >= b)
q[cnt ++] = {l[i].y, r[i].y};
if (!cnt) return 0;
sort(q, q + cnt);
LL res = 0;
int st = q[0].x, ed = q[0].y;
for (int i = 1; i < cnt; i ++)
if (q[i].x <= ed) ed = max(ed, q[i].y);
else
{
res += ed - st;
st = q[i].x, ed = q[i].y;
}
res += ed - st;
return res * (b - a);
}
int main()
{
YuXiao();
cin >> n;
for (int i = 0; i < n; i ++)
{
cin >> l[i].x >> l[i].y >> r[i].x >> r[i].y;
xs.push_back(l[i].x), xs.push_back(r[i].x);
}
sort(xs.begin(), xs.end());
LL res = 0;
for (int i = 0; i < xs.size() - 1; i ++)
if (xs[i] != xs[i + 1])
res += range_area(xs[i], xs[i + 1]);
cout << res << endl;
return 0;
}
三维凸包
/* 立体(三维)几何:立方体*/
struct CH3D {
struct Plane {
int a, b, c; // 凸包一个面上三个点的编号
bool ok; // 该面是否属于凸包上的面
};
int n, num; // 初始顶点数、凸包表面的三角形数
Point3 P[N]; // 凸包表面的三角形数
Plane F[N * 8];
int g[N][N];
void read(int i) {
cin >> P[i].x >> P[i].y >> P[i].z;
}
double volume4(Point3 a, Point3 b, Point3 c, Point3 d) { // 四面体有向体积 * 6
return dot(cross(b - a, c - a), d - a);
}
double cmp3(Point3 &a, Plane &f) { // 为正:点在面同向
Point3 p1 = P[f.b] - P[f.a];
Point3 p2 = P[f.c] - P[f.a];
Point3 p3 = a - P[f.a];
return dot(cross(p1, p2), p3);
}
void deal(int p, int a, int b) {
int f = g[a][b];
Plane add;
if (F[f].ok) {
if (cmp3(P[p], F[f]) > eps) {
dfs(p, f);
} else {
add.a = b, add.b = a, add.c = p, add.ok = true;
g[p][b] = g[a][p] = g[b][a] = num;
F[num ++] = add;
}
}
}
void dfs(int p, int now) { // 递归搜索所有应该从凸包内删除的面
F[now].ok = false;
deal(p, F[now].b, F[now].a);
deal(p, F[now].c, F[now].b);
deal(p, F[now].a, F[now].c);
}
bool same(int s, int t) {
Point3 &a = P[F[s].a];
Point3 &b = P[F[s].b];
Point3 &c = P[F[s].c];
return fabs(volume4(a, b, c, P[F[t].a])) < eps &&
fabs(volume4(a, b, c, P[F[t].b])) < eps &&
fabs(volume4(a, b, c, P[F[t].c])) < eps;
}
void get_convex3() { // 三维凸包
num = 0;
Plane add;
/* -------------------------保证四个点不共面---------------------------- */
bool flag = true;
for (int i = 1; i < n; i ++) {
if (!(P[0] == P[i])) {
swap(P[1], P[i]);
flag = false;
break;
}
}
if (flag) { return ; } flag = true;
for (int i = 2; i < n; i ++) {
if (length((cross(P[1] - P[0], P[i] - P[0]))) > eps) {
swap(P[2], P[i]);
flag = false;
break;
}
}
if (flag) { return ; } flag = true;
for (int i = 3; i < n; i ++) {
if (fabs(dot(cross(P[1] - P[0], P[2] - P[0]), P[i] - P[0])) > eps) {
swap(P[3], P[i]);
flag = false;
break;
}
}
if (flag) { return ; }
/* ---------------------------------------------------------------------- */
for (int i = 0; i < 4; i ++) {
add.a = (i + 1) % 4, add.b = (i + 2) % 4, add.c = (i + 3) % 4, add.ok = true;
if (cmp3(P[i], add) > 0) {
swap(add.b, add.c);
}
g[add.a][add.b] = g[add.b][add.c] = g[add.c][add.a] = num;
F[num ++] = add;
}
for (int i = 4; i < n; i ++) {
for (int j = 0; j < num; j ++) {
if (F[j].ok && cmp3(P[i], F[j]) > eps) {
dfs(i, j);
break;
}
}
}
int tmp = num; num = 0;
for (int i = 0; i < tmp; i ++) {
if (F[i].ok) {
F[num ++] = F[i];
}
}
}
double convex3_area() { // 表面积
double res = 0;
if (n == 3) {
Vector3 p = cross(P[2] - P[0], P[1] - P[0]);
return length(p) / 2;
}
for (int i = 0; i < num; i ++) {
res += length(area(P[F[i].a], P[F[i].b], P[F[i].c]));
}
return res / 2;
}
double volume() { // 体积
double res = 0;
Point3 tmp = Point3(0, 0, 0);
for (int i = 0; i < num; i ++) {
res += volume4(tmp, P[F[i].a], P[F[i].b], P[F[i].c]);
}
return fabs(res / 6);
}
int triangle() { // 表面三角形个数
return num;
}
int polygon() { // 表面多边形个数
int res = 0;
for (int i = 0; i < num; i ++) {
bool flag = true;
for (int j = 0; j < i; j ++) {
if (same(i, j)) {
flag = false;
break;
}
}
res += flag;
}
return res;
}
Point3 center() { // 重心
Point3 res = Point3(0, 0, 0);
Point3 o = Point3(0, 0, 0);
double all = 0;
for (int i = 0; i < num; i ++) {
double v = volume4(o, P[F[i].a], P[F[i].b], P[F[i].c]);
res = res + (((o + P[F[i].a] + P[F[i].b] + P[F[i].c]) / 4) * v);
all += v;
}
res = res / all;
return res;
}
double PP_distance(Point3 p, int i) { // 点到面的距离
double a = fabs(volume4(P[F[i].a], P[F[i].b], P[F[i].c], p));
double b = length(cross(P[F[i].b] - P[F[i].a], P[F[i].c] - P[F[i].a]));
return a / b;
}
};
三角形面积并
/*
Created by YuXiao
Nothing to say.
*/
// O(n^3logn)
#define YuXiao() cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <iomanip>
#define x first
#define y second
using namespace std;
typedef pair<double, double> PDD;
const int N = 110;
const double eps = 1e-8, INF = 1e6;
int n;
PDD tr[N][3];
PDD q[N];
PDD operator+ (PDD a, PDD b) { return {a.x + b.x, a.y + b.y}; }
PDD operator- (PDD a, PDD b) { return {a.x - b.x, a.y - b.y}; }
PDD operator* (PDD a, double t) { return {a.x * t, a.y * t}; }
double operator* (PDD a, PDD b) { return a.x * b.y - a.y * b.x; }
PDD operator/ (PDD a, double t) { return {a.x / t, a.y / t}; }
double operator& (PDD a, PDD b) { return a.x * b.x + a.y * b.y; }
int sign(double x)
{
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
return 1;
}
int dcmp(double x, double y)
{
if (fabs(x - y) < eps) return 0;
if (x < y) return -1;
return 1;
}
bool on_segment(PDD p, PDD a, PDD b)
{
return sign((p - a) & (p - b)) <= 0;
}
PDD get_line_intersection(PDD p, PDD v, PDD q, PDD w)
{
if (!sign(v * w)) return {INF, INF};
auto u = p - q;
auto t = w * u / (v * w);
auto o = p + v * t;
if (!on_segment(o, p, p + v) || !on_segment(o, q, q + w))
return {INF, INF};
return o;
}
double line_area(double a, int side)
{
int cnt = 0;
for (int i = 0; i < n; i ++)
{
auto t = tr[i];
if (dcmp(t[0].x, a) > 0 || dcmp(t[2].x, a) < 0) continue;
if (!dcmp(t[0].x, a) && !dcmp(t[1].x, a))
{
if (side) q[cnt ++] = {t[0].y, t[1].y};
}
else if (!dcmp(t[2].x, a) && !dcmp(t[1].x, a))
{
if (!side) q[cnt ++] = {t[2].y, t[1].y};
}
else
{
double d[3];
int u = 0;
for (int j = 0; j < 3; j ++)
{
auto o = get_line_intersection(t[j], t[(j + 1) % 3] - t[j], {a, -INF}, {0, INF * 2});
if (dcmp(o.x, INF)) d[u ++] = o.y;
}
if (u)
{
sort(d, d + u);
q[cnt ++] = {d[0], d[u - 1]};
}
}
}
if (!cnt) return 0;
for (int i = 0; i < cnt; i ++)
if (q[i].x > q[i].y)
swap(q[i].x, q[i].y);
sort(q, q + cnt);
double res = 0, st = q[0].x, ed = q[0].y;
for (int i = 1; i < cnt; i ++)
if (q[i].x <= ed) ed = max(ed, q[i].y);
else
{
res += ed - st;
st = q[i].x, ed = q[i].y;
}
res += ed - st;
return res;
}
double range_area(double a, double b)
{
return (line_area(a, 1) + line_area(b, 0)) * (b - a) / 2;
}
int main()
{
YuXiao();
cin >> n;
vector<double> xs;
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < 3; j ++)
{
cin >> tr[i][j].x >> tr[i][j].y;
xs.push_back(tr[i][j].x);
}
sort(tr[i], tr[i] + 3);
}
for (int i = 0; i < n; i ++)
for (int j = i + 1; j < n; j ++)
for (int x = 0; x < 3; x ++)
for (int y = 0; y < 3; y ++)
{
auto o = get_line_intersection(tr[i][x], tr[i][(x + 1) % 3] - tr[i][x],
tr[j][y], tr[j][(y + 1) % 3] - tr[j][y]);
if (dcmp(o.x, INF)) xs.push_back(o.x);
}
sort(xs.begin(), xs.end());
double res = 0;
for (int i = 0; i < xs.size() - 1; i ++)
if (dcmp(xs[i], xs[i + 1]))
res += range_area(xs[i], xs[i + 1]);
cout << fixed << setprecision(2) << res << endl;
return 0;
}
三角剖分
/*
Created by YuXiao
Nothing to say.
*/
#define YuXiao() cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iomanip>
#define x first
#define y second
using namespace std;
typedef pair<double, double> PDD;
const int N = 60;
const double eps = 1e-8, PI = acos(-1);
double R;
int n;
PDD q[N], r;
PDD operator+ (PDD a, PDD b) { return {a.x + b.x, a.y + b.y}; }
PDD operator- (PDD a, PDD b) { return {a.x - b.x, a.y - b.y}; }
PDD operator* (PDD a, double t) { return {a.x * t, a.y * t}; }
double operator* (PDD a, PDD b) { return a.x * b.y - a.y * b.x; }
PDD operator/ (PDD a, double t) { return {a.x / t, a.y / t}; }
double operator& (PDD a, PDD b) { return a.x * b.x + a.y * b.y; }
int sign(double x)
{
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
return 1;
}
int dcmp(double x, double y)
{
if (fabs(x - y) < eps) return 0;
if (x < y) return -1;
return 1;
}
double area(PDD a, PDD b, PDD c)
{
return (b - a) * (c - a);
}
double get_len(PDD a)
{
return sqrt(a & a);
}
double get_dist(PDD a, PDD b)
{
return get_len(b - a);
}
double project(PDD a, PDD b, PDD c)
{
return ((c - a) & (b - a)) / get_len(b - a);
}
PDD rotate(PDD a, double b)
{
return {a.x * cos(b) + a.y * sin(b), -a.x * sin(b) + a.y * cos(b)};
}
PDD norm(PDD a)
{
return a / get_len(a);
}
bool on_segment(PDD p, PDD a, PDD b)
{
return !sign((p - a) * (p - b)) && sign((p - a) & (p - b)) <= 0;
}
PDD get_line_intersection(PDD p, PDD v, PDD q, PDD w)
{
auto u = p - q;
auto t = w * u / (v * w);
return p + v * t;
}
double get_circle_line_intersection(PDD a, PDD b, PDD &pa, PDD &pb)
{
auto e = get_line_intersection(a, b - a, r, rotate(b - a, PI / 2));
auto mind = get_dist(r, e);
if (!on_segment(e, a, b)) mind = min(get_dist(r, a), get_dist(r, b));
if (dcmp(R, mind) <= 0) return mind;
auto len = sqrt(R * R - get_dist(r, e) * get_dist(r, e));
pa = e + norm(a - b) * len;
pb = e + norm(b - a) * len;
return mind;
}
double get_sector(PDD a, PDD b)
{
auto angle = acos((a & b) / get_len(a) / get_len(b));
if (sign(a * b) < 0) angle = -angle;
return R * R * angle / 2;
}
double get_circle_triangle_area(PDD a, PDD b)
{
auto da = get_dist(r, a), db = get_dist(r, b);
if (dcmp(R, da) >= 0 && dcmp(R, db) >= 0) return a * b / 2;
if (!sign(a * b)) return 0;
PDD pa, pb;
auto mind = get_circle_line_intersection(a, b, pa, pb);
if (dcmp(R, mind) <= 0) return get_sector(a, b);
if (dcmp(R, da) >= 0) return a * pb / 2 + get_sector(pb, b);
if (dcmp(R, db) >= 0) return get_sector(a, pa) + pa * b / 2;
return get_sector(a, pa) + pa * pb / 2 + get_sector(pb, b);
}
double work()
{
double res = 0;
for (int i = 0; i < n; i ++)
res += get_circle_triangle_area(q[i], q[(i + 1) % n]);
return fabs(res);
}
int main()
{
YuXiao();
while (cin >> R >> n)
{
for (int i = 0; i < n; i ++) cin >> q[i].x >> q[i].y;
cout << fixed << setprecision(2) << work() << endl;
}
return 0;
}
半平面交
double half_plane_intersection() { // 半平面交
sort(l, l + cnt, lcmp);
int hh = 0, tt = -1;
for (int i = 0; i < cnt; i ++) {
if (i && !dcmp(angle(l[i]), angle(l[i - 1]))) continue;
while (hh + 1 <= tt && PL_relation(line_intersection(l[q[tt - 1]], l[q[tt]]), l[i]) == 1) tt --;
while (hh + 1 <= tt && PL_relation(line_intersection(l[q[hh]], l[q[hh + 1]]), l[i]) == 1) hh ++;
q[++ tt] = i;
}
while (hh + 1 <= tt && PL_relation(line_intersection(l[q[tt - 1]], l[q[tt]]), l[hh]) == 1) tt --;
while (hh + 1 <= tt && PL_relation(line_intersection(l[q[hh]], l[q[hh + 1]]), l[tt]) == 1) hh ++;
q[++ tt] = q[hh];
int k = 0;
for (int i = hh; i < tt; i ++) ans[k ++] = line_intersection(l[q[i]], l[q[i + 1]]);
double res = 0;
for (int i = 1; i + 1 < k; i ++) res += area(ans[0], ans[i], ans[i + 1]);
return res / 2;
}
评论