针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)。
有兴趣的同学可以扫码添加我们的微信(code5bug)了解,免费试课一下。
流浪地球计划在赤道上均匀部署了N个转向发动机,按位置顺序编号为0~N。
1). 初始状态下所有的发动机都是未启动状态;
2). 发动机启动的方式分为”手动启动”和”关联启动”两种方式;
3). 如果在时刻1一个发动机被启动,下一个时刻2与之相邻的两个发动机就会被"关联启动”;
4). 如果准备启动某个发动机时,它已经被启动了,则什么都不用做;
5). 发动机0与发动机N-1是相邻的;
地球联合政府准备挑选某些发动机在某些时刻进行"手动启动”。当然最终所有的发动机都会被启动。
哪些发动机最晚被启动呢?
第一行两个数字N和E,中间有空格N代表部署发动机的总个数,E代表计划手动启动的发动机总个数 1 接下来共E行,每行都是两个数字T和P,中间有空格T代表发动机的手动启动时刻,P代表此发动机的位置编号。0 <= T <= N 0 <= P < N 第一行一个数字N,以回车结束N代表最后被启动的发动机个数 第二行N个数字,中间有空格,以回车结束每个数字代表发动机的位置编号,从小到大排序 这道题是一个典型的 广度优先搜索(BFS) 问题。我们需要模拟发动机的启动过程,找到最后被启动的发动机。 整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。输出描述
示例1
输入:
8 2
0 2
0 6
输出:
2
0 4
说明:
8个发动机;
时刻0启动(2,6);
时刻1启动(1,3,5,7)(其中1,3被2关联启动,5,7被6关联启动)
时刻2启动(0,4)(其中0被1,7关联启动,4被3,5关联启动);
至此所有发动机都被启动,最后被启动的有2个,分别是0和4。
Java
import java.util.*;
/**
* @author code5bug
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取N和E
int n = scanner.nextInt();
int e = scanner.nextInt();
// 优先队列,根据启动时刻排序,时刻越早优先级越高
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
// 读取E行手动启动的事件
for (int i = 0; i < e; i++) {
int t = scanner.nextInt();
int p = scanner.nextInt();
pq.offer(new int[]{t, p});
}
// 已经启动的发动机集合
Set<Integer> started = new HashSet<>();
// 记录最后一批启动的发动机
List<Integer> last = new ArrayList<>();
// BFS 执行,处理每个时刻的启动事件
while (!pq.isEmpty()) {
last.clear(); // 清空上一轮启动的发动机
// 获取当前时刻启动的所有发动机
int time = pq.peek()[0]; // 当前时刻
while (!pq.isEmpty() && pq.peek()[0] == time) {
int p = pq.poll()[1]; // 发动机位置
// 如果该发动机已经启动,跳过
if (started.contains(p)) {
continue;
} else {
// 启动该发动机
started.add(p);
last.add(p);
// 启动该发动机后,需要启动它的相邻发动机(循环队列)
int lp = (p - 1 + n) % n; // 左邻居
int rp = (p + 1) % n; // 右邻居
// 如果左邻居没有启动,安排它在下一个时刻启动
if (!started.contains(lp)) pq.offer(new int[]{time + 1, lp});
// 如果右邻居没有启动,安排它在下一个时刻启动
if (!started.contains(rp)) pq.offer(new int[]{time + 1, rp});
}
}
}
// 最后启动的发动机从小到大排序
Collections.sort(last);
// 输出最后被启动的发动机的数量和编号
System.out.println(last.size());
for (int i = 0; i < last.size(); i++) {
if (i + 1 == last.size()) {
System.out.println(last.get(i));
} else {
System.out.print(last.get(i) + " ");
}
}
}
}
1. 题目类型
2. 解题思路
N
和 E
,其中 N
代表发动机的总数,E
代表计划手动启动的发动机的数量。接着读取每个手动启动事件,包括启动的时刻和发动机的位置编号。(启动时刻, 发动机位置)
这样的二元组,优先级是按时刻从小到大排序的。
HashSet
来记录已启动的发动机,避免重复启动。