• [kuangbin] 专题13 基础计算几何 题解 + 总结


    kuangbin带你飞点击进入新世界

    [kuangbin] 专题7 线段树 题解 + 总结:https://www.cnblogs.com/RioTian/p/13413897.html

    kuangbin专题十二 基础DP1 题解+总结:https://www.cnblogs.com/RioTian/p/13110438.html

    kuangbin专题六 最小生成树 题解+总结:https://www.cnblogs.com/RioTian/p/13380764.html

    [kuangbin]专题九 连通图 题解+总结 : https://www.cnblogs.com/RioTian/p/13395039.html

    计算几何分类blog:https://www.cnblogs.com/RioTian/category/1852545.html


    总结

    1、TOYS POJ - 2318

    题目链接: Click Here

    题目大意: 有一个方盒子 有N个板隔开 分成N+1个区域
    又给了M个玩具的坐标 问你每个区域内(不能恰好在区域内)的玩具有几个(忽略玩具体积)

    解题思路: 每相邻的两个板看成两个向量 分别求其与其中一点和玩具坐标的叉积 如果两叉积的乘积<0 就说明这个玩具坐标点在一个板的右边 一个板的左边

    因为数据量比较大 可以把板和方盒的两边记录下来 然后二分 道理是一样的

    AC代码:

    Code
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #define ms(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    const int N = 5000 + 10;
    int num[N], x[N], y[N];
    struct node {
        double x, y;
    } pu[N], pl[N], q;
    int n, m, f;
    int mul(node p1, node p2, node p3) {
        return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
    }
    void Bisearch(node x) {
        int l = 0, r = n + 1, ans;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (mul(x, pu[mid], pl[mid]) < 0)
                ans = mid, r = mid - 1;
            else
                l = mid + 1;
        }
        num[ans - 1]++;
    }
    int main() {
        // freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
        int x1, x2, y1, y2;
        while (cin >> n) {
            if (n == 0) break;
            ms(num, 0);
            cin >> m >> x1 >> y1 >> x2 >> y2;
            // scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
            pu[0].x = x1, pu[0].y = y1;
            pl[0].x = x1, pl[0].y = y2;
            for (int i = 1; i <= n; ++i) {
                // scanf("%d %d", &pu[i].x, &pl[i].x);
                cin >> pu[i].x >> pl[i].x;
                pu[i].y = y1, pl[i].y = y2;
            }
            pu[n + 1].x = x2, pu[n + 1].y = y1;
            pl[n + 1].x = x2, pl[n + 1].y = y2;
            for (int i = 0; i < m; i++) {
                // scanf("%d %d", &q.x, &q.y);
                cin >> q.x >> q.y;
                Bisearch(q);
            }
            if (f == 1) printf("
    ");
            f = 1;
            for (int i = 0; i <= n; i++) printf("%d: %d
    ", i, num[i]);
        }
    }
    

    另一种写法

    Code
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    typedef double db;
    const int maxn = 5e3 + 5;
    const db eps = 1e-10;
    int dcmp(db x) {
        if(fabs(x) < eps) {
            return 0;
        }
        return x > 0? 1: -1;
    }
    struct Point {
        double x, y;
        Point(double xx = 0, double yy = 0) : x(xx), y(yy) {}
        void input() {
            scanf("%lf%lf", &x, &y);
        }
        Point operator-(const Point a) {
            return Point(x - a.x, y - a.y);
        }
        db cross(const Point a) {
            return x * a.y - y * a.x;
        }
    };
    typedef Point Vector;
    struct Line {
        Point s, e;
        Line() {}
        Line(Point s, Point e) : s(s), e(e) {}
        int toLeftTest(Point p) {
            if((e - s).cross(p - s) > 0) return 1;
            else if((e - s).cross(p - s) < 0) return -1;
            return 0;
        }
    };
    int n, m;
    Line line[maxn];
    Point point[maxn];
    int ans[maxn];
    void solve() {
        for(int i = 1; i <= m; ++i) {
            int l = 0, r = n + 1;
            int mid = (l + r) >> 1;
            while(l + 1 < r) {
                if(line[mid].toLeftTest(point[i]) > 0) {
                    r = mid;
                } else {
                    l = mid;
                }
                mid = (l + r) >> 1;
            }
            ans[l]++;
        }
        for(int i = 0; i <= n; ++i) {
            printf("%d: %d
    ", i, ans[i]);
        }
        printf("
    ");
    }
    int main() {
        while(scanf("%d", &n) != EOF && n) {
            memset(ans, 0, sizeof(ans));
            scanf("%d", &m);
            db xl, yl, xr, yr;
            scanf("%lf%lf%lf%lf", &xl, &yl, &xr, &yr);
            line[0].s = Point(xl, yr);
            line[0].e = Point(xl, yl);
            line[n + 1].s = Point(xr, yr);
            line[n + 1].e = Point(xr, yl);
            for(int i = 1; i <= n; ++i) {
                db u, l;
                scanf("%lf%lf", &u, &l);
                line[i].s = Point(l, yr);
                line[i].e = Point(u, yl);
            }
            for(int i = 1; i <= m; ++i) {
                scanf("%lf%lf", &point[i].x, &point[i].y);
            }
            solve();
        }
        return 0;
    }
    

    2、Toy Storage POJ - 2398

    题目链接:Click Here

    POJ 2318 类似,不同的是这次给定的线段是乱序的,因此先要排序。输出也不同,改一下即可。

    Code
    // Author : RioTian
    // Time : 20/10/21
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    typedef double db;
    const int maxn = 5e3 + 5;
    const db eps = 1e-10;
    int dcmp(db x) {
        if (fabs(x) < eps) {
            return 0;
        }
        return x > 0 ? 1 : -1;
    }
    struct Point {
        double x, y;
        Point(double xx = 0, double yy = 0) : x(xx), y(yy) {}
        void input() { scanf("%lf%lf", &x, &y); }
        bool operator<(const Point &a) const {
            return (!dcmp(x - a.x)) ? dcmp(y - a.y) < 0 : x < a.x;
        }
        Point operator-(const Point a) { return Point(x - a.x, y - a.y); }
        db cross(const Point a) { return x * a.y - y * a.x; }
    };
    typedef Point Vector;
    struct Line {
        Point s, e;
        Line() {}
        Line(Point s, Point e) : s(s), e(e) {}
        bool operator<(const Line &a) const { return s < a.s; }
        int toLeftTest(Point p) {
            if ((e - s).cross(p - s) > 0)
                return 1;
            else if ((e - s).cross(p - s) < 0)
                return -1;
            return 0;
        }
    };
    int cmp(Line a, Line b) { return a.s < b.s; }
    int n, m;
    Line line[maxn];
    Point point[maxn];
    int ans[maxn];
    int cnt[maxn];
    void solve() {
        for (int i = 1; i <= m; ++i) {
            int l = 0, r = n + 1;
            int mid = (l + r) >> 1;
            while (l + 1 < r) {
                if (line[mid].toLeftTest(point[i]) > 0) {
                    r = mid;
                } else {
                    l = mid;
                }
                mid = (l + r) >> 1;
            }
            ans[l]++;
        }
        int max_size = 0;
        for (int i = 0; i <= n; ++i) {
            if (ans[i]) {
                cnt[ans[i]]++;
                max_size = max(max_size, ans[i]);
            }
        }
        printf("Box
    ");
        for (int i = 1; i <= max_size; ++i) {
            if (cnt[i]) {
                printf("%d: %d
    ", i, cnt[i]);
            }
        }
    }
    int main() {
        while (scanf("%d", &n) != EOF && n) {
            memset(ans, 0, sizeof(ans));
            memset(cnt, 0, sizeof(cnt));
            scanf("%d", &m);
            db xl, yl, xr, yr;
            scanf("%lf%lf%lf%lf", &xl, &yl, &xr, &yr);
            line[0].s = Point(xl, yr);
            line[0].e = Point(xl, yl);
            line[n + 1].s = Point(xr, yr);
            line[n + 1].e = Point(xr, yl);
            for (int i = 1; i <= n; ++i) {
                db u, l;
                scanf("%lf%lf", &u, &l);
                line[i].s = Point(l, yr);
                line[i].e = Point(u, yl);
            }
            sort(line + 1, line + 1 + n);  // 要对线段排序
            for (int i = 1; i <= m; ++i) {
                scanf("%lf%lf", &point[i].x, &point[i].y);
            }
            solve();
        }
        return 0;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    [转]C#获取程序当前路径的方法
    [解决办法]未在本地计算机上注册“Mircosoft.Jet.OleDB.4.0”提供程序
    [解决办法]正在尝试使用已关闭或释放并且不再有效的 SPWeb 对象
    PowerShell学习笔记
    DNS
    在C#编程中,如何将Excel保存为2003的格式
    SAAS相关网络资源
    LCID及Culture Name列表
    Microsoft's naming conventions (微软命名规范)
    C#中如何结束Excel (Office)进程
  • 原文地址:https://www.cnblogs.com/RioTian/p/13848250.html
Copyright © 2020-2023  润新知