3.招募队员【算法赛】 - 蓝桥云课 (lanqiao.cn)
问题描述
为了对抗蠢蠢欲动的异能兽,炎龙侠、飞鹰侠、黑犀侠、雪獒侠和地虎侠五位铠甲勇士决定各自组建战队,迎战强敌。
消息一出,光影村的铠甲后人热血沸腾,纷纷组队报名。
现共有 𝑛n 支队伍,每支队伍由五名年轻小伙组成,他们各自填写了最想跟随的铠甲勇士编号(11 代表炎龙侠,22 代表飞鹰侠,以此类推,55 代表地虎侠)。用 𝑎𝑖,𝑗ai,j 表示第 𝑖i 支队伍的第 𝑗j 名队员最想跟随的铠甲勇士的编号。例如,𝑎3,2=4a3,2=4 就表示第 33 支队伍的第 22 名队员想加入雪獒侠的战队。
为了公平公正,每位铠甲勇士需从报名队伍中选择一个连续的区间 [𝑙,𝑟][l,r](1≤𝑙≤𝑟≤𝑛1≤l≤r≤n)进行招募。但有一个重要的规则:对于区间内的每一支队伍,该铠甲勇士必须且只能招募一名心仪他的队员。如果某支队伍中没有队员想跟随这位铠甲勇士,那么这位铠甲勇士就不能选择包含这支队伍的区间。
现在,五位铠甲勇士都想知道自己最多能招募到多少队员,以便制定最佳的作战策略。你能帮助他们计算出各自可招募的最大人数吗?
输入格式
第一行包含一个整数 𝑛n(1≤𝑛≤1051≤n≤105),表示报名队伍的总数。
接下来 𝑛n 行,每行包含五个整数 𝑎𝑖,1,𝑎𝑖,2,𝑎𝑖,3,𝑎𝑖,4,𝑎𝑖,5ai,1,ai,2,ai,3,ai,4,ai,5(1≤𝑎𝑖,𝑗≤51≤ai,j≤5),表示第 𝑖i 支队伍中五名队员想跟随的铠甲勇士编号。
输出格式
输出一行,包含五个整数,分别表示炎龙侠、飞鹰侠、黑犀侠、雪獒侠和地虎侠最多能招募到的队员数量。
样例输入
5
1 2 3 4 5
1 2 3 4 5
1 1 1 1 1
1 2 3 4 5
1 2 3 4 5
样例输出
5 2 2 2 2
运行限制
语言 | 最大运行时间 | 最大运行内存 |
---|---|---|
C++ | 1s | 256M |
C | 1s | 256M |
Java | 2s | 256M |
Python3 | 3s | 256M |
PyPy3 | 3s | 256M |
Go | 3s | 256M |
JavaScript | 3s | 256M |
import java.util.ArrayList;
import java.util.Scanner;
// 主类,按照题目要求类名必须为Main
public class Main {
public static void main(String[] args) {
// 创建Scanner对象用于从控制台读取用户输入
Scanner scan = new Scanner(System.in);
// 读取报名队伍的总数n
int n = scan.nextInt();
// 创建一个二维的ArrayList,用于存储每支队伍队员想跟随的铠甲勇士编号信息
// 外层ArrayList对应每支队伍,内层ArrayList对应每支队伍里的五名队员的选择
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
// 循环读取每支队伍的信息
for (int i = 0; i < n; i++) {
// 为每支队伍创建一个新的内层ArrayList,用于存储该队伍五名队员的选择
list.add(new ArrayList<>());
// 循环读取该队伍里五名队员想跟随的铠甲勇士编号,并添加到内层ArrayList中
for (int j = 0; j < 5; j++) {
list.get(i).add(scan.nextInt());
}
}
// 依次计算每位铠甲勇士(编号从1到5)最多能招募到的队员数量
for (int i = 1; i <= 5; i++) {
int max = 0; // 用于记录当前铠甲勇士能招募到的最大连续队员数量
int c = 0; // 用于临时记录当前连续区间内想跟随当前铠甲勇士的队员数量
// 遍历每支队伍,检查队伍中是否有队员想跟随当前铠甲勇士(编号为i)
for (int j = 0; j < list.size(); j++) {
// 如果当前队伍中有队员想跟随当前铠甲勇士(编号为i)
if (list.get(j).contains(i)) {
c++;
} else {
// 如果当前队伍中没有队员想跟随当前铠甲勇士,更新最大连续队员数量max
// 并重置临时计数c为0,准备统计下一个可能的连续区间
max = Math.max(max, c);
c = 0;
}
}
// 处理最后一个连续区间的情况,更新最大连续队员数量max
max = Math.max(max, c);
// 输出当前铠甲勇士(编号为i)最多能招募到的队员数量
System.out.print(max + " ");
}
// 关闭Scanner,释放资源
scan.close();
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
// 主类,按照题目要求类名通常为Main(这里假设是满足相关编程作业或测试要求的类名)
public class Main {
// 创建一个静态的BufferedReader对象,用于从标准输入流(通常是控制台)读取字符数据
// 它通过将System.in包装在InputStreamReader中实现高效的字符读取
static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 创建一个静态的PrintWriter对象,用于向标准输出流(通常是控制台)写入格式化后的文本数据
static final PrintWriter pw = new PrintWriter(System.out);
// 主方法,程序的入口点,当程序启动时会首先执行这个方法
public static void main(String[] args) throws IOException {
// 从标准输入读取一个整数n,表示后续输入数据的组数或相关循环次数等(具体含义需结合题目上下文)
int n = Integer.parseInt(br.readLine());
// 创建一个长度为6的整数数组cnt,用于记录某种计数情况(结合后续代码可能是与1到5这几个数字相关的计数)
// 数组索引0位置未使用,索引1到5分别对应相关情况的计数
int[] cnt = new int[6];
// 创建一个长度为6的整数数组ans,用于存储最终的结果(同样索引0位置未使用,索引1到5对应相关结果)
int[] ans = new int[6];
// 开始一个循环,循环次数由之前读取的n决定
for (int i = 0; i < n; i++) {
// 使用Java 8的流(Stream)特性将从控制台读取的一行字符串数据(以空格分隔的数字字符串)
// 先进行分割操作得到字符串数组,然后将每个字符串转换为整数,并收集到一个Set集合中
// 这样可以去除重复的数字,并且便于后续判断某个数字是否在集合中
Set<Integer> set = Arrays.stream(br.readLine().split(" "))
.map(Integer::parseInt).collect(Collectors.toSet());
// 遍历数字1到5
for (int j = 1; j <= 5; j++) {
// 如果当前集合set中包含数字j,说明出现了一次与j相关的情况,对cnt数组中对应的索引位置计数加1
if (set.contains(j)) cnt[j]++;
// 如果当前集合set中不包含数字j,说明出现了一次间断情况
// 此时需要比较当前间断情况下之前连续出现的与j相关的最大次数(存储在ans[j]中)和当前连续计数cnt[j]
// 取两者中的较大值更新ans[j],然后将cnt[j]重置为0,准备统计下一次可能的连续情况
else {
ans[j] = Math.max(ans[j], cnt[j]);
cnt[j] = 0;
}
}
}
// 循环结束后,再次遍历数字1到5
for (int i = 1; i <= 5; i++) {
// 处理最后一次循环结束后可能还未更新的情况,再次比较ans[i]和cnt[i]的大小
// 取两者中的较大值更新ans[i],确保ans[i]存储的是最终的最大相关次数
ans[i] = Math.max(ans[i], cnt[i]);
// 将最终的结果(每个数字对应的最大相关次数)输出到标准输出流,每个结果之间用空格隔开
pw.print(ans[i] + " ");
}
// 关闭PrintWriter,确保所有缓冲的数据都被正确写入到标准输出流中,释放相关资源
pw.close();
}
}