码迷,mamicode.com
首页 > 其他好文 > 详细

2018 ICPC Asia Xuzhou Regional M. Rikka with Illuminations

时间:2020-12-10 11:38:18      阅读:15      评论:0      收藏:0      [点我收藏+]

标签:else   size   max   cross   ast   std   lan   push   struct   

题意:

一个凸多边形和\(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\n", (int)vec.size());
            for (int i = 0; i < vec.size(); i++)
                printf("%d%c", vec[i], " \n"[i == vec.size() - 1]);
        }
    }
    return 0;
}

2018 ICPC Asia Xuzhou Regional M. Rikka with Illuminations

标签:else   size   max   cross   ast   std   lan   push   struct   

原文地址:https://www.cnblogs.com/Zeronera/p/14093694.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!