zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    图01--[基本概念&&图的实现]
    并查集01--[Quick Find&&Quick Union]
    排序05--[计数排序&&基数排序&&桶排序]
    排序04--[快速排序&&希尔排序]
    harukaの赛前日常
    harukaの收藏夹
    hello world&Restart the Journey
    成外集训小记
    CSPS2019游记
    博弈论初步
  • 原文地址:https://www.cnblogs.com/Zeronera/p/14093694.html
Copyright © 2011-2022 走看看