计算几何

#include <bits/stdc++.h>
#define rep(i, L, R) for (int i = L; i <= R; ++i)
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const int N = 1e5 + 7;
inline int sgn(double x) {
    if (fabs(x) < eps) return 0;
    return x > 0 ? 1 : -1;
}
struct Point {
    double x, y;
    Point() = default;
    Point(double x, double y) : x(x), y(y) {}
    Point operator+(const Point &a) const { return Point(x + a.x, y + a.y); }
    Point operator-(const Point &a) const { return Point(x - a.x, y - a.y); }
    Point operator*(const double &k) const { return Point(k * x, k * y); }
    double operator*(const Point &a) const { return x * a.x + y * a.y; }
    double operator^(const Point &a) const { return x * a.y - y * a.x; }
    Point operator/(double k) { return {x / k, y / k}; };
    bool is_par(const Point &a) const { return abs((*this) ^ a) <= eps; }
    double len2() const { return (*this) * (*this); }
    double dis2(const Point &a) const { return (a - (*this)).len2(); }
};

struct Line {
    Point p, v;
    Line() = default;
    Line(Point p, Point v) : p(p), v(v){};
    Point inter(const Line &a) const {
        return p + v * ((a.v ^ (p - a.p)) / (v ^ a.v));
    }
} line;
int dcmp(double x) {
    if (fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
double dis(Point a, Point b) { return hypot(a.x - b.x, a.y - b.y); }
typedef Point vec;
double cross(vec a, vec b) { return a.x * b.y - a.y * b.x; } // 向量积
double S(Point *a, int n) {  //数组起始位置 多边形有多少个点
    double res = 0;
    for (int i = 0; i < n; ++i) res += cross(a[i], a[(i + 1) % n]);
    return res / 2;  // 面积有正负
}
Point center(Point *a, int n) {  // 求重心
    Point ans = {0, 0};
    double Sa = S(a, n);
    if (Sa == 0) return ans;
    for (int i = 0; i < n; ++i)
        ans = ans + (a[i] + a[(i + 1) % n]) * cross(a[i], a[(i + 1) % n]);
    return ans / Sa / 6;
}

// bool line_segment_intersect(Line L, Point A, Point B, Point &P) {
//     Point a = A - L.B, b = L.A - L.B, c = B - L.B;
//     if (dcmp(cross(a, b)) * dcmp(cross(b, c)) >= 0) {
//         Point u = L.A - A;
//         double t = cross(A - B, u) / cross(b, A - B);
//         P = L.A + b * t;
//         return true;
//     }
//     return false;
// }
bool isIN(Point A, Line L) {
    double x = min(L.p.x, L.v.x);
    double xx = max(L.p.x, L.v.x);
    double y = min(L.p.y, L.v.y);
    double yy = max(L.p.y, L.v.y);
    return A.x <= xx and A.x >= x and A.y <= yy and A.y >= y;
}
bool isIN1(Point A, Point B, Point C) { return (B - A) * (A - C) >= -eps; }
Point a[N];
int T, n;
int main() {
    cout << isIN({1, 1}, {{2, 2}, {3, 3}}) << endl;
    cout << isIN({2, 2}, {{1, 1}, {3, 3}}) << endl;
    Line a = {{0, 0}, {0, 2}};
    Line b = {{1, 1}, {-1, 1}};
    cout << a.inter(b).x << ' ' << a.inter(b).y << '\n';
    // scanf("%d", &n);
    // rep(i, 1, n) scanf("%lf%lf", &a[i].x, &a[i].y);
    // Point o = center(a + 1, n);
    // double ans = 1e18;

    // rep(th, 0, 3600) {
    //     double x = o.x + cos(th * 1.0 / 10), y = o.y + sin(th * 1.0 / 10);
    //     Line lx = {o, Point{x, y}};
    //     Point P, Q;
    //     int f = 0;
    //     rep(i, 2, n) {
    //         Line ly = {a[i - 1], a[i]};
    //         Point T = lx.inter(ly);
    //         // if (f == 0 and isIN(T, ly)) {
    //         //     P = T;
    //         //     ++f;
    //         // }
    //         // if (f == 1 and isIN(T, ly)) {
    //         //     Q = T;
    //         //     ++f;
    //         //     break;
    //         // }

    //         if (f == 0 and isIN1(T, a[i - 1], a[i])) {
    //             P = T;
    //             ++f;
    //         }
    //         if (f == 1 and isIN1(T, a[i - 1], a[i])) {
    //             Q = T;
    //             ++f;
    //             break;
    //         }
    //     }
    //     if (f == 1) Q = lx.inter({a[n], a[1]}), ++f;
    //     //  cerr << P.x << ' ' << P.y << endl;
    //     // if (dcmp(P.x) == 0 and dcmp(P.y) == 0)
    //     //     cerr << Q.x << ' ' << Q.y << endl;
    //     if (f == 2) {
    //         double d = dis(P, Q);
    //         if (d > -1e18) ans = min(d, ans);
    //     }
    // }
    // cout << ans;

    return 0;
}
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;
#define eps 1e-8

int n;

int dcmp(double x) {
    if (fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}

struct Point {
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) {}
    bool operator!=(const Point &p) {
        return dcmp(x - p.x) != 0 || (dcmp(x - p.x) == 0 && dcmp(y - p.y) != 0);
    }
    friend Point operator+(Point A, Point B) {
        return Point(A.x + B.x, A.y + B.y);
    }
    friend Point operator-(Point A, Point B) {
        return Point(A.x - B.x, A.y - B.y);
    }
    friend Point operator*(Point A, double d) {
        return Point(A.x * d, A.y * d);
    }
    friend Point operator/(Point A, double d) {
        return Point(A.x / d, A.y / d);
    }
} p[30];

struct Line {
    Point A, B;
} line;

double dot(Point A, Point B) { return A.x * B.x + A.y * B.y; }

double cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }

double polygon_area() {
    double area = 0;
    for (int i = 1; i < n - 1; i++) area += cross(p[i] - p[0], p[i + 1] - p[0]);
    return fabs(area) / 2;
}

bool line_segment_intersect(Line L, Point A, Point B, Point &P) {
    Point a = A - L.B, b = L.A - L.B, c = B - L.B;
    if (dcmp(cross(a, b)) * dcmp(cross(b, c)) >= 0) {
        Point u = L.A - A;
        double t = cross(A - B, u) / cross(b, A - B);
        P = L.A + b * t;
        return true;
    }
    return false;
}

int main() {
    Point a;
    cout << line_segment_intersect({{1, 1}, {-1, 1}}, {0, 0}, {0, 2}, a)
         << endl;
    cout << a.x << ' ' << a.y << endl;

    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
    scanf("%lf%lf%lf%lf", &line.A.x, &line.A.y, &line.B.x, &line.B.y);
    int flag = 0;
    double sum1 = polygon_area(), sum2 = 0;
    Point P, T;
    p[n] = p[0];
    for (int i = 0; i < n; i++) {
        if (flag == 0 && line_segment_intersect(line, p[i], p[i + 1], P)) {
            sum2 += cross(P, p[i + 1]);
            flag++;
        } else if (flag == 1 &&
                   line_segment_intersect(line, p[i], p[i + 1], T) && P != T) {
            sum2 += cross(p[i], T);
            sum2 += cross(T, P);
            flag++;
            break;
        } else if (flag == 1)
            sum2 += cross(p[i], p[i + 1]);
    }
    sum2 = fabs(sum2) / 2;
    sum1 -= sum2;
    if (sum1 < sum2) swap(sum1, sum2);
    printf("%.0lf %.0lf\n", sum1, sum2);

    return 0;
}
#include <bits/stdc++.h>
#define rep(i, L, R) for (int i = L; i <= R; ++i)
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const int N = 1000007;
inline int sgn(double x) {
    if (fabs(x) < eps) return 0;
    return x > 0 ? 1 : -1;
}
struct point {
    double x, y;
    point operator+(point b) { return {x + b.x, y + b.y}; };
    point operator-(point b) { return {x - b.x, y - b.y}; };
    point operator*(double k) { return {x * k, y * k}; };
    point operator/(double k) { return {x / k, y / k}; };
};
struct Line {
    point A, B;
} line;
int dcmp(double x) {
    if (fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
double dis(point a, point b) { return hypot(a.x - b.x, a.y - b.y); }
typedef point vec;
double cross(vec a, vec b) { return a.x * b.y - a.y * b.x; }
double S(point *a, int n) {  //数组起始位置 多边形有多少个点
    double res = 0;
    for (int i = 0; i < n; ++i) res += cross(a[i], a[(i + 1) % n]);
    return res / 2;  // 面积有正负
}
point center(point *a, int n) {  // 求重心
    point ans = {0, 0};
    double Sa = S(a, n);
    if (Sa == 0) return ans;
    for (int i = 0; i < n; ++i)
        ans = ans + (a[i] + a[(i + 1) % n]) * cross(a[i], a[(i + 1) % n]);
    return ans / Sa / 6;
}
bool line_segment_intersect(Line L, point A, point B, point &P) {
    point a = A - L.B, b = L.A - L.B, c = B - L.B;
    if (dcmp(cross(a, b)) * dcmp(cross(b, c)) >= 0) {
        point u = L.A - A;
        double t = cross(A - B, u) / cross(b, A - B);
        P = L.A + b * t;
        return true;
    }
    return false;
}
point a[N];
int T, n;
int main() {
    scanf("%d", &n);
    rep(i, 1, n) scanf("%lf%lf", &a[i].x, &a[i].y);
    point o = center(a + 1, n);
    double ans = 1e18;
    rep(th, 0, 3600) {
        double x = o.x + cos(th * 1.0 / 10), y = o.y + sin(th * 1.0 / 10);
        Line lx = {o, point{x, y}};
        point P, Q;
        int f = 0;
        rep(i, 2, n) {
            if (!f && line_segment_intersect(line, a[i - 1], a[i], P)) f = 1;
            if (f) {
                if (line_segment_intersect(line, a[i - 1], a[i], Q)) {
                    f = 2;
                    break;
                }
            }
        }
        if (f == 1) {
            line_segment_intersect(line, a[n], a[1], Q);
        }
        double d = dis(P, Q);
        ans = min(d, ans);
    }
    cout << ans;

    return 0;
}
算法竞赛之路 文章被收录于专栏

整理、记录算法竞赛的好题

全部评论

相关推荐

07-22 11:53
门头沟学院 Java
终于有一个保底的offer了,但感觉是白菜价
北凝a:我想问问,提前批的offer 有问你啥时候到岗吗,如果你还想找其他的怎么办
点赞 评论 收藏
分享
07-24 12:30
湘潭大学 营销
点赞 评论 收藏
分享
水墨不写bug:疑似没有上过大学
点赞 评论 收藏
分享
仁者伍敌:牛子这些人还会点一个自动回复,boss都不带回复的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务