欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

贪心 E - Radar Installation

程序员文章站 2022-07-11 11:58:22
...

E - Radar Installation

题目链接:E - Radar Installation
贪心 E - Radar Installation

题解

思路

题目要求找到可以覆盖所有岛屿的最少雷达数量。
由于雷达所能覆盖的范围是一定的,那么一个岛屿可以被覆盖到的临界条件是该岛屿在雷达探测范围的边界上,即以该岛屿为顶点,以雷达探测半径为腰,以x轴为底,所得的等腰三角形。
每一个岛屿都可以得到这样一个等腰三角形。根据等腰三角形与x轴的交点,我们可以得到覆盖该岛屿的雷达所在的区间。

对于得到的区间a[x, y], b[xx, yy],可能存在以下情况:

  1. b 区间在 a 区间内;
  2. b 区间与 a 区间相等;
  3. b 区间与 a 区间有交叉;
  4. b 区间与 a 区间无交集;
  5. b 区间与 a 区间相邻;
  6. a 区间在b区间内。

以上情况中只有第4种情况需要添加新的雷达。

实现

如果对所有区间都与其他所有区间进行如上六种判断,时间复杂度会很大。
我们可以先对所有的岛屿的坐标的x坐标进行升序排序,这样,所有的岛屿区间只会有以下几种情况:

对于排序后的区间岛屿a[x, y],岛屿b[xx, yy] (a在b左侧):

  1. b 在 a 内;
  2. b 与 a 有交集(b的左边界在a区间内);
  3. b 与 a 无交集;
  4. b 与 a 交与 a 的右边界点;
  5. b 与 a 相等。

看似仅仅减少了1中情况,实际上,以上多种情况可以合并,且由于进行了排序,我们只需要维护一个左边界和一个右边界即可。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#include<vector>
#include<set>
#include<fstream>

using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(a, b) memcpy(a, b, sizeof(b))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;

namespace FastIO {
    const int bufsiz = 1 << 22;
    char buf[bufsiz];

    inline char getch() {
        static int tot;
        tot++;
        if (tot == bufsiz) {
            fread(buf, 1, bufsiz, stdin);
            tot = 0;
        }
        return buf[tot];
    }

    inline int read() {
        int x = 0;
        char c = getch();
        while (!isdigit(c))c = getch();
        while (isdigit(c))x = x * 10 + c - '0', c = getch();
        return x;
    }
}
using FastIO::read;

bool cmp(const P &x, const P &y) {
    return x.first < y.first;
}

vector<P> v(1010);

int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    int n, d;
    int cnt = 0;
    while (scanf("%d%d", &n, &d) && n != 0) {
        v.clear();
        bool ff = false;
        rep(i, 0, n - 1) {
            int x, y;
            scanf("%d%d", &x, &y);
            if (y > d) ff = true;
            v[i].first = x, v[i].second = y;
//            v.push_back(P(x, y));
        }
        if (ff) {
            printf("Case %d: -1\n", ++cnt);
            continue;
        }
        sort(v.begin(), v.begin() + n, cmp);
        int ans = 1;
        float x = -INF, y = INF;
        rep(i, 0, n - 1) {
            float lo = sqrt((float) (d * d - v[i].second * v[i].second));
            float xx = v[i].first - lo, yy = v[i].first + lo;
            if (x <= xx && yy <= y) x = xx, y = yy;
            else if (x <= xx && xx <= y && xx <= y && y <= yy) x = xx, y = y;
            else if (y == xx) x = xx, y = xx;
            else if (xx <= x && y <= yy) x = x, y = y;
            else if (y < xx) {
                ans++;
                x = xx, y = yy;
            }
        }
        printf("Case %d: %d\n", ++cnt, ans);
    }
    return 0;
}