跳到主要内容

智破连环阵

信息

此题目来自 洛谷, 原始题目与提交代码请前往 P1526 [NOI2003] 智破连环阵 - 洛谷

题目描述

B 国在耗资百亿元之后终于研究出了新式武器——连环阵(Zenith Protected Linked Hybrid Zone)。 传说中,连环阵是一种永不停滞的自发性智能武器。 但经过 A 国间谍的侦察发现,连环阵其实是由 MM 个编号为 1,2,,M1,2,\dots,M 的独立武器组成的。 最初,11 号武器发挥着攻击作用,其他武器都处在无敌自卫状态。 以后,一旦第 ii1i<M{1}\le{i}<{M})号武器被消灭,11 秒种以后第 i+1i+1 号武器就自动从无敌自卫状态变成攻击状态。 当第 MM 号武器被消灭以后,这个造价昂贵的连环阵就被摧毁了。

为了彻底打击 B 国科学家,A 国军事部长打算用最廉价的武器——炸弹来消灭连环阵。 经过长时间的精密探测,A 国科学家们掌握了连环阵中 MM 个武器的平面坐标,然后确定了 nn 个炸弹的平面坐标并且安放了炸弹。 每个炸弹持续爆炸时间为 55 分钟。 在引爆时间内,每枚炸弹都可以在瞬间消灭离它平面距离不超过 kk 的、处在攻击状态的 B 国武器。 和连环阵类似,最初 a1{a}_{1} 号炸弹持续引爆 55 分钟时间,然后 a2{a}_{2} 号炸弹持续引爆 55 分钟时间,接着 a3{a}_{3} 号炸弹引爆... 以此类推,直到连环阵被摧毁。

显然,不同的序列 a1,a2,a3{a}_{1},{a}_{2},{a}_{3}\dots 消灭连环阵的效果也不同。 好的序列可以在仅使用较少炸弹的情况下就将连环阵摧毁; 坏的序列可能在使用完所有炸弹后仍无法将连环阵摧毁。 现在,请你决定一个最优序列 a1,a2,a3{a}_{1},{a}_{2},{a}_{3}\dots 使得在第 ax{a}_{x} 号炸弹引爆的时间内连环阵被摧毁。 这里的 xx 应当尽量小。

输入格式

第一行包含三个整数:MMnnkk,分别表示 B 国连环阵由 MM 个武器组成,A 国有 nn 个炸弹可以使用,炸弹攻击范围为 kk。 以下 MM 行,每行由一对整数 xi,yi{x}_{i},{y}_{i} 组成,表示第 ii 号武器的平面坐标。 再接下来 nn 行,每行由一对整数 ui,vi{u}_{i},{v}_{i} 组成,表示第 ii 号炸弹的平面坐标。 输入数据保证随机、无误、并且必然有解。

输出格式

一行包含一个整数 xx,表示实际使用的炸弹数。

输入输出样例

输入 #1

4 3 6
0 6
6 6
6 0
0 0
1 5
0 3
1 1

输出 #1

2

说明/提示

对于 100%100\% 的数据,1M,n100{1}\le{M},{n}\le{100}1k1000{1}\le{k}\le{1000}0xi,yi10000{0}\le{{x}_{i}},{{y}_{i}}\le{10000}0ui,vi10000{0}\le{{u}_{i}},{{v}_{i}}\le{10000}

各个测试点 22 秒。

题目解答

注意

本题题解尚未完成/尚未完善, 不足以 AC 通过评判。

已知共有 MM 个武器、nn 个炸弹 (范围为 kk)

为了方便解题,我们可以先定义一个工具类:

using namespace std;

/**
* 二维点工具类。
* @author CoolCLK
*/
template<typename T>
class Point {
private:
pair<T, T> position;

public:
Point(T x, T y) {
this -> position = pair(x, y);
}

bool isInDistance(Point<T> other, T d) {
T dx = position.first - other.position.first, dy = position.second - other.position.second, dd = d * d;
dx *= dx;
dy *= dy;
return dx + dy <= dd;
}
};

很好,接下来就是获取数据:

#include <iostream>
#include <vector>
#define repeat(n) for (size_t _= 0; _ < n; _++)
typedef unsigned int u_int;
using namespace std;

void acceptInput() {}

/**
* 接受多个参数的输入。
* @author CoolCLK
*/
template <typename T, typename... Args>
void acceptInput(T& first, Args&... args) {
std::cin >> first;
acceptInput(args...);
}

class Point { /* 此处省略部分代码 */ };

int main() {
u_int M, n, k;
vector<Point<u_int>> weapons;
vector<Point<u_int>> bombs;
acceptInput(M, n, k);
repeat(M) {
u_int x, y;
acceptInput(x, y);
weapons.emplace_back(x, y);
}
repeat(n) {
u_int x, y;
acceptInput(x, y);
bombs.emplace_back(x, y);
}
return 0;
}

很容易发现,我们还有一个条件没有用到:

......
以后,一旦第 i(1≤i<M)号武器被消灭,1 秒种以后第 i+1 号武器就自动从无敌自卫状态变成攻击状态。
......
每个炸弹持续爆炸时间为 5 分钟。
......

同时,为了方便统计,我们可以定义一个长度为 nn 的布尔数组来储存是否用到这个炸弹。

那么,我们来定义它们。

u_int BOMB_DURATION = 300; // 5min * 60s/min = 300s
vector<bool> bombsUsed(n, false);

之后,我们就只需要关注主方法即可。