• 2018 ICPC Asia Xuzhou Regional M. Rikka with Illuminations


    题意:

    一个凸多边形和(m)个光源,问最少选择几个光源使得多边形所有边都被照亮

    思路:

    对于每个光源,处理出能照到的边,即为区间完全覆盖问题,但是区间是环形的,枚举起点处理

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const double eps = 1e-8;
    const int maxn = 10010;
    int sgn(double x) { return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1); }
    struct Point {
        double x, y;
        Point() {}
        Point(double _x, double _y) {
            x = _x;
            y = _y;
        }
        void input() {
            scanf("%lf%lf", &x, &y);
        }
        Point operator-(const Point &b) const {
            return Point(x - b.x, y - b.y);
        }
        double operator^(const Point &b) const {
            return x * b.y - y * b.x;
        }
    };
    double cross(Point A, Point B, Point C) {
        return (B - A) ^ (C - A);
    }
    Point p[maxn], a[maxn];
    struct s {
        int l, r, id;
    } b[maxn];
    vector<int> ans;
    int solve(int st, int num, int len) {
        int last = 0, far = 0, cnt = 0, now;
        int start = b[st].l;
        for (int i = 0; i < num; i++) {
            if (last >= len) return cnt;
            if (b[i].l - start <= last) {
                if (far < b[i].r - start) {
                    far = b[i].r - start;
                    now = b[i].id;
                }
            } else {
                cnt++;
                ans.push_back(now);
                last = far;
                if (b[i].l - start <= last) {
                    if (far < b[i].r - start) {
                        far = b[i].r - start;
                        now = b[i].id;
                    }
                } else
                    return -1;
            }
        }
        if (last < len && far >= len) {
            ans.push_back(now);
            return cnt + 1;
        }
        if (far < len) return -1;
        return cnt;
    }
    int main() {
        int n, m, t;
        scanf("%d", &t);
        while (t--) {
            ans.clear();
            scanf("%d%d", &n, &m);
            for (int i = 0; i < n; i++) p[i].input();
            for (int i = 0; i < n; i++) p[i + n] = p[i];
            for (int i = 0; i < m; i++) a[i].input();
            for (int i = 0; i < m; i++) {
                int j = 0;
                while (sgn(cross(p[j], p[j + 1], a[i])) < 0) j++;
                while (sgn(cross(p[j], p[j + 1], a[i])) > 0) j++;
                int pos = j;
                while (sgn(cross(p[j], p[j + 1], a[i])) < 0) j++;
                b[i * 2] = {pos, j, i + 1};
                b[i * 2 + 1] = {pos + n, j + n, i + 1};
            }
            m *= 2;
            sort(b, b + m, [&](s x, s y) {
                return x.l < y.l;
            });
            vector<int> vec;
            int sz = 1e9;
            for (int i = 0; i < m; i++) {
                ans.clear();
                int res = solve(i, m, n);
                if (res == -1) continue;
                if (res < sz) {
                    sz = res;
                    vec = ans;
                }
            }
            if (sz == 1e9)
                puts("-1");
            else {
                printf("%d
    ", (int)vec.size());
                for (int i = 0; i < vec.size(); i++)
                    printf("%d%c", vec[i], " 
    "[i == vec.size() - 1]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    总结(1)--- 数据库
    在路上---学习篇(一)Python 数据结构和算法 (4) --希尔排序、归并排序
    在路上---学习篇(一)Python 数据结构和算法 (3) --快速排序
    在路上---学习篇(一)Python 数据结构和算法 (2) -- 冒泡排序、选择排序、插入排序
    javascript观察者模式
    es6对象的扩展
    es6数组的扩展
    vue全局API
    javascript原型链
    简单工厂,工厂方法模式
  • 原文地址:https://www.cnblogs.com/Zeronera/p/14093694.html
Copyright © 2020-2023  润新知