解题报告 『Raid(分治)』

Posted kirisame-marisa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题报告 『Raid(分治)』相关的知识,希望对你有一定的参考价值。

原题地址

大概翻译一下题意:

在与联邦的战争接连失败之后,帝国方面撤退到了最后的据点。凭借着强大的防御系统,帝国军击退了联邦的六波进攻。经过几天不眠不休的思考,Arthur,联邦统帅,注意到防御系统的唯一弱点是它的能源供应。该系统由n个核电站进行充电,任何一个核电站的故障都会导致系统失效。

将军很快就发动了一次突袭,突袭者是准备潜行进入要塞的N名特工。不幸的是,由于帝国空军的攻击,他们未能按预期的位置着陆。作为一名经验丰富的将军,Arthur很快意识到他需要重新安排计划。他现在想知道的第一件事是哪个特工离任何一个发电站最近。大副,你能帮解决将军这个问题吗?

 

其实就是求最近点对,只不过两个点必须处于不同的集合,用分治乱搞一下就过了。

 

代码实现如下:

技术图片
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

const int inf = 0x3f3f3f3f, maxn = 1e5 + 5;

int T, n;
double ans;

struct node {
    int x, y, id;
}p[maxn], q[maxn];

int cmp_x(node a, node b) {return a.x < b.x;}

int cmp_y(node a, node b) {return a.y < b.y;}

int ABS(int a, int b) {return a > b ? a - b : b - a;}

double MIN(double a, double b) {return a < b ? a : b;}

int read() {
    int x = 0, flag = 0;
    char ch =  ;
    while (ch != - && (ch < 0 || ch > 9)) ch = getchar();
    if (ch == -) {
        flag = 1;
        ch = getchar();
    }
    while (ch >= 0 && ch <= 9) {
        x = (x << 1) + (x << 3) + ch - 0;
        ch = getchar();
    }
    return flag ? -x : x;
}

double dis(node a, node b) {
    if (a.id == b.id) return inf;
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double divide(int l, int r) {
    if (l == r) return inf;
    int cnt = 0, mid = (l + r) >> 1;
    double ans = MIN(divide(l, mid), divide(mid + 1, r));
    rep(i, l, r) {
        if (ABS(p[i].x, p[mid].x) > ans) break;
        else q[++cnt] = p[i];
    }
    sort(q + 1, q + cnt + 1, cmp_y);
    rep(i, 1, cnt)
        rep(j, 1, cnt) {
            if (ABS(q[i].y, q[j].y) > ans) break;//复制粘贴时忘了把mid改成j,快调吐血了才发现这个傻逼错误.
            else ans = MIN(ans, dis(q[i], q[j]));
        }
    return ans;  
}

int main() {
    T = read();
    while (T--) {
        n = read();
        rep(i, 1, n << 1) {
            p[i].x = read(), p[i].y = read();
            if (i <= n) p[i].id = 0;
            else p[i].id = 1;
        }
        sort(p + 1, p + (n << 1) + 1, cmp_x);
        ans = divide(1, n << 1);
        printf("%.3f\n", ans);
    }
    return 0;
}
View Code

以上是关于解题报告 『Raid(分治)』的主要内容,如果未能解决你的问题,请参考以下文章

poj3714 Raid(分治求平面最近点对)

| 分治-奇袭raid

$Poj3714/AcWing Raid$ 分治/平面最近点对

[解题报告]《算法零基础100讲》(第27讲) 字符串算法 - 高精度

麦森数(分治或快速幂)

POJ 3714 Raid