#C256. 【华为OD机考 统一考试机试C卷】小朋友分组最少调整次数
【华为OD机考 统一考试机试C卷】小朋友分组最少调整次数
题目链接
【华为OD机考 统一考试机试C卷】小朋友分组最少调整次数(C++ Java JavaScript Python C语言)
https://blog.csdn.net/banxia_frontend/article/details/136192490
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取并解析初始的学生(序号)排队顺序
int[] initialOrder = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int studentCount = initialOrder.length;
// 创建序号到组号的映射关系数组
int[] groupMapping = new int[studentCount + 1];
for (int i = 0; i < studentCount; i++) {
int studentNumber = scanner.nextInt(); // 读取每个学生的序号
groupMapping[studentNumber] = i / 3; // 每三个学生分为一组,映射组号
}
// 创建一个链表用于合并相邻相同组号的学生
LinkedList<int[]> groupQueue = new LinkedList<>();
for (int studentNumber : initialOrder) {
int groupId = groupMapping[studentNumber]; // 获取学生对应的组号
if (groupQueue.isEmpty() || groupQueue.getLast()[0] != groupId) {
// 如果队列为空或者最后一个组与当前学生组不同,新增一个组
groupQueue.addLast(new int[]{groupId, 1});
} else {
// 如果最后一个组与当前学生组相同,则增加该组的学生数
groupQueue.getLast()[1]++;
}
}
// 记录需要调整的次数
int adjustmentCount = 0;
while (!groupQueue.isEmpty()) {
int[] currentGroup = groupQueue.removeFirst(); // 取出第一个组
if (currentGroup[1] == 1) {
// 如果当前组只有一个学生
int[] nextGroup = groupQueue.getFirst(); // 获取下一个组
while (nextGroup[1] == 3) {
// 如果下一个组的学生数为3,继续获取下一个组
groupQueue.removeFirst();
nextGroup = groupQueue.getFirst();
}
if (nextGroup[0] == currentGroup[0] && nextGroup[1] == 2) {
// 如果下一个组与当前组组号相同且有两个学生,则需要一次调整
adjustmentCount++;
groupQueue.removeFirst(); // 移除下一个组
} else {
// 否则需要两次调整
adjustmentCount += 2;
// 重新排列剩余的组
LinkedList<int[]> rearrangedQueue = new LinkedList<>();
while (!groupQueue.isEmpty()) {
int[] group = groupQueue.removeFirst();
if (group[0] == currentGroup[0]) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedQueue.isEmpty() || rearrangedQueue.getLast()[0] != group[0]) {
rearrangedQueue.addLast(new int[]{group[0], group[1]});
} else {
rearrangedQueue.getLast()[1] += group[1];
}
}
groupQueue = rearrangedQueue; // 更新队列
}
} else if (currentGroup[1] == 2) {
// 如果当前组有两个学生
adjustmentCount += 1;
// 重新排列剩余的组
LinkedList<int[]> rearrangedQueue = new LinkedList<>();
while (!groupQueue.isEmpty()) {
int[] group = groupQueue.removeFirst();
if (group[0] == currentGroup[0]) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedQueue.isEmpty() || rearrangedQueue.getLast()[0] != group[0]) {
rearrangedQueue.addLast(new int[]{group[0], group[1]});
} else {
rearrangedQueue.getLast()[1] += group[1];
}
}
groupQueue = rearrangedQueue; // 更新队列
}
}
System.out.println(adjustmentCount); // 输出调整次数
}
}
python
import sys
from collections import deque
# 读取输入
input = sys.stdin.read
data = input().split()
# 初始排队顺序
initial_order = list(map(int, data[:data.index("")]))
# 分组排队顺序
group_order = list(map(int, data[data.index("") + 1:]))
# 学生总数
student_count = len(initial_order)
# 创建序号到组号的映射关系数组
group_mapping = [0] * (student_count + 1)
for i in range(student_count):
student_number = group_order[i] # 读取每个学生的序号
group_mapping[student_number] = i // 3 # 每三个学生分为一组,映射组号
# 创建一个链表用于合并相邻相同组号的学生
group_queue = deque()
for student_number in initial_order:
group_id = group_mapping[student_number] # 获取学生对应的组号
if not group_queue or group_queue[-1][0] != group_id:
# 如果队列为空或者最后一个组与当前学生组不同,新增一个组
group_queue.append([group_id, 1])
else:
# 如果最后一个组与当前学生组相同,则增加该组的学生数
group_queue[-1][1] += 1
# 记录需要调整的次数
adjustment_count = 0
while group_queue:
current_group = group_queue.popleft() # 取出第一个组
if current_group[1] == 1:
# 如果当前组只有一个学生
next_group = group_queue[0] # 获取下一个组
while next_group[1] == 3:
# 如果下一个组的学生数为3,继续获取下一个组
group_queue.popleft()
next_group = group_queue[0]
if next_group[0] == current_group[0] and next_group[1] == 2:
# 如果下一个组与当前组组号相同且有两个学生,则需要一次调整
adjustment_count += 1
group_queue.popleft() # 移除下一个组
else:
# 否则需要两次调整
adjustment_count += 2
# 重新排列剩余的组
rearranged_queue = deque()
while group_queue:
group = group_queue.popleft()
if group[0] == current_group[0]:
continue # 跳过与当前组号相同的组
if not rearranged_queue or rearranged_queue[-1][0] != group[0]:
rearranged_queue.append([group[0], group[1]])
else:
rearranged_queue[-1][1] += group[1]
group_queue = rearranged_queue # 更新队列
elif current_group[1] == 2:
# 如果当前组有两个学生
adjustment_count += 1
# 重新排列剩余的组
rearranged_queue = deque()
while group_queue:
group = group_queue.popleft()
if group[0] == current_group[0]:
continue # 跳过与当前组号相同的组
if not rearranged_queue or rearranged_queue[-1][0] != group[0]:
rearranged_queue.append([group[0], group[1]])
else:
rearranged_queue[-1][1] += group[1]
group_queue = rearranged_queue # 更新队列
print(adjustment_count) # 输出调整次数
javascript
const readline = require('readline');
// 创建接口以读取标准输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 读取输入数据
let inputLines = [];
rl.on('line', (line) => {
inputLines.push(line);
if (inputLines.length === 2) {
rl.close();
}
});
rl.on('close', () => {
// 初始排队顺序
let initialOrder = inputLines[0].split(' ').map(Number);
// 分组排队顺序
let groupOrder = inputLines[1].split(' ').map(Number);
// 学生总数
let studentCount = initialOrder.length;
// 创建序号到组号的映射关系数组
let groupMapping = new Array(studentCount + 1).fill(0);
for (let i = 0; i < studentCount; i++) {
let studentNumber = groupOrder[i]; // 读取每个学生的序号
groupMapping[studentNumber] = Math.floor(i / 3); // 每三个学生分为一组,映射组号
}
// 创建一个队列用于合并相邻相同组号的学生
let groupQueue = [];
for (let studentNumber of initialOrder) {
let groupId = groupMapping[studentNumber]; // 获取学生对应的组号
if (groupQueue.length === 0 || groupQueue[groupQueue.length - 1][0] !== groupId) {
// 如果队列为空或者最后一个组与当前学生组不同,新增一个组
groupQueue.push([groupId, 1]);
} else {
// 如果最后一个组与当前学生组相同,则增加该组的学生数
groupQueue[groupQueue.length - 1][1]++;
}
}
// 记录需要调整的次数
let adjustmentCount = 0;
while (groupQueue.length > 0) {
let currentGroup = groupQueue.shift(); // 取出第一个组
if (currentGroup[1] === 1) {
// 如果当前组只有一个学生
let nextGroup = groupQueue[0]; // 获取下一个组
while (nextGroup[1] === 3) {
// 如果下一个组的学生数为3,继续获取下一个组
groupQueue.shift();
nextGroup = groupQueue[0];
}
if (nextGroup[0] === currentGroup[0] && nextGroup[1] === 2) {
// 如果下一个组与当前组组号相同且有两个学生,则需要一次调整
adjustmentCount++;
groupQueue.shift(); // 移除下一个组
} else {
// 否则需要两次调整
adjustmentCount += 2;
// 重新排列剩余的组
let rearrangedQueue = [];
while (groupQueue.length > 0) {
let group = groupQueue.shift();
if (group[0] === currentGroup[0]) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedQueue.length === 0 || rearrangedQueue[rearrangedQueue.length - 1][0] !== group[0]) {
rearrangedQueue.push([group[0], group[1]]);
} else {
rearrangedQueue[rearrangedQueue.length - 1][1] += group[1];
}
}
groupQueue = rearrangedQueue; // 更新队列
}
} else if (currentGroup[1] === 2) {
// 如果当前组有两个学生
adjustmentCount += 1;
// 重新排列剩余的组
let rearrangedQueue = [];
while (groupQueue.length > 0) {
let group = groupQueue.shift();
if (group[0] === currentGroup[0]) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedQueue.length === 0 || rearrangedQueue[rearrangedQueue.length - 1][0] !== group[0]) {
rearrangedQueue.push([group[0], group[1]]);
} else {
rearrangedQueue[rearrangedQueue.length - 1][1] += group[1];
}
}
groupQueue = rearrangedQueue; // 更新队列
}
}
console.log(adjustmentCount); // 输出调整次数
});
C++
#include <iostream>
#include <vector>
#include <sstream>
#include <queue>
#include <string>
using namespace std;
int main() {
string initialOrderLine, groupOrderLine;
getline(cin, initialOrderLine); // 读取初始排队顺序
getline(cin, groupOrderLine); // 读取分组排队顺序
// 将初始排队顺序解析为整数数组
stringstream initialStream(initialOrderLine);
vector<int> initialOrder;
int num;
while (initialStream >> num) {
initialOrder.push_back(num);
}
int studentCount = initialOrder.size();
// 将分组排队顺序解析为整数数组
stringstream groupStream(groupOrderLine);
vector<int> groupOrder;
while (groupStream >> num) {
groupOrder.push_back(num);
}
// 创建序号到组号的映射关系数组
vector<int> groupMapping(studentCount + 1, 0);
for (int i = 0; i < studentCount; i++) {
int studentNumber = groupOrder[i]; // 读取每个学生的序号
groupMapping[studentNumber] = i / 3; // 每三个学生分为一组,映射组号
}
// 创建一个队列用于合并相邻相同组号的学生
deque<pair<int, int>> groupQueue;
for (int studentNumber : initialOrder) {
int groupId = groupMapping[studentNumber]; // 获取学生对应的组号
if (groupQueue.empty() || groupQueue.back().first != groupId) {
// 如果队列为空或者最后一个组与当前学生组不同,新增一个组
groupQueue.emplace_back(groupId, 1);
} else {
// 如果最后一个组与当前学生组相同,则增加该组的学生数
groupQueue.back().second++;
}
}
// 记录需要调整的次数
int adjustmentCount = 0;
while (!groupQueue.empty()) {
pair<int, int> currentGroup = groupQueue.front(); // 取出第一个组
groupQueue.pop_front();
if (currentGroup.second == 1) {
// 如果当前组只有一个学生
pair<int, int> nextGroup = groupQueue.front(); // 获取下一个组
while (nextGroup.second == 3) {
// 如果下一个组的学生数为3,继续获取下一个组
groupQueue.pop_front();
nextGroup = groupQueue.front();
}
if (nextGroup.first == currentGroup.first && nextGroup.second == 2) {
// 如果下一个组与当前组组号相同且有两个学生,则需要一次调整
adjustmentCount++;
groupQueue.pop_front(); // 移除下一个组
} else {
// 否则需要两次调整
adjustmentCount += 2;
// 重新排列剩余的组
deque<pair<int, int>> rearrangedQueue;
while (!groupQueue.empty()) {
pair<int, int> group = groupQueue.front();
groupQueue.pop_front();
if (group.first == currentGroup.first) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedQueue.empty() || rearrangedQueue.back().first != group.first) {
rearrangedQueue.emplace_back(group.first, group.second);
} else {
rearrangedQueue.back().second += group.second;
}
}
groupQueue = rearrangedQueue; // 更新队列
}
} else if (currentGroup.second == 2) {
// 如果当前组有两个学生
adjustmentCount += 1;
// 重新排列剩余的组
deque<pair<int, int>> rearrangedQueue;
while (!groupQueue.empty()) {
pair<int, int> group = groupQueue.front();
groupQueue.pop_front();
if (group.first == currentGroup.first) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedQueue.empty() || rearrangedQueue.back().first != group.first) {
rearrangedQueue.emplace_back(group.first, group.second);
} else {
rearrangedQueue.back().second += group.second;
}
}
groupQueue = rearrangedQueue; // 更新队列
}
}
// 输出调整次数
cout << adjustmentCount << endl;
return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义结构体用于存储组号和组内学生数
typedef struct {
int groupId;
int studentCount;
} Group;
int main() {
char initialOrderLine[90001], groupOrderLine[90001];
fgets(initialOrderLine, sizeof(initialOrderLine), stdin); // 读取初始排队顺序
fgets(groupOrderLine, sizeof(groupOrderLine), stdin); // 读取分组排队顺序
// 将初始排队顺序解析为整数数组
int initialOrder[30000];
int studentCount = 0;
char *token = strtok(initialOrderLine, " ");
while (token != NULL) {
initialOrder[studentCount++] = atoi(token);
token = strtok(NULL, " ");
}
// 将分组排队顺序解析为整数数组
int groupOrder[30000];
int index = 0;
token = strtok(groupOrderLine, " ");
while (token != NULL) {
groupOrder[index++] = atoi(token);
token = strtok(NULL, " ");
}
// 创建序号到组号的映射关系数组
int groupMapping[studentCount + 1];
for (int i = 0; i < studentCount; i++) {
int studentNumber = groupOrder[i]; // 读取每个学生的序号
groupMapping[studentNumber] = i / 3; // 每三个学生分为一组,映射组号
}
// 创建一个队列用于合并相邻相同组号的学生
Group groupQueue[30000];
int queueSize = 0;
for (int i = 0; i < studentCount; i++) {
int studentNumber = initialOrder[i];
int groupId = groupMapping[studentNumber]; // 获取学生对应的组号
if (queueSize == 0 || groupQueue[queueSize - 1].groupId != groupId) {
// 如果队列为空或者最后一个组与当前学生组不同,新增一个组
groupQueue[queueSize].groupId = groupId;
groupQueue[queueSize].studentCount = 1;
queueSize++;
} else {
// 如果最后一个组与当前学生组相同,则增加该组的学生数
groupQueue[queueSize - 1].studentCount++;
}
}
// 记录需要调整的次数
int adjustmentCount = 0;
int front = 0;
while (front < queueSize) {
Group currentGroup = groupQueue[front]; // 取出第一个组
if (currentGroup.studentCount == 1) {
// 如果当前组只有一个学生
Group nextGroup = groupQueue[front + 1]; // 获取下一个组
while (nextGroup.studentCount == 3) {
// 如果下一个组的学生数为3,继续获取下一个组
front++;
nextGroup = groupQueue[front + 1];
}
if (nextGroup.groupId == currentGroup.groupId && nextGroup.studentCount == 2) {
// 如果下一个组与当前组组号相同且有两个学生,则需要一次调整
adjustmentCount++;
front++; // 移除下一个组
} else {
// 否则需要两次调整
adjustmentCount += 2;
// 重新排列剩余的组
Group rearrangedQueue[30000];
int rearrangedSize = 0;
for (int i = front + 1; i < queueSize; i++) {
Group group = groupQueue[i];
if (group.groupId == currentGroup.groupId) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedSize == 0 || rearrangedQueue[rearrangedSize - 1].groupId != group.groupId) {
rearrangedQueue[rearrangedSize].groupId = group.groupId;
rearrangedQueue[rearrangedSize].studentCount = group.studentCount;
rearrangedSize++;
} else {
rearrangedQueue[rearrangedSize - 1].studentCount += group.studentCount;
}
}
memcpy(groupQueue + front + 1, rearrangedQueue, rearrangedSize * sizeof(Group)); // 更新队列
queueSize = front + 1 + rearrangedSize;
}
} else if (currentGroup.studentCount == 2) {
// 如果当前组有两个学生
adjustmentCount += 1;
// 重新排列剩余的组
Group rearrangedQueue[30000];
int rearrangedSize = 0;
for (int i = front + 1; i < queueSize; i++) {
Group group = groupQueue[i];
if (group.groupId == currentGroup.groupId) {
continue; // 跳过与当前组号相同的组
}
if (rearrangedSize == 0 || rearrangedQueue[rearrangedSize - 1].groupId != group.groupId) {
rearrangedQueue[rearrangedSize].groupId = group.groupId;
rearrangedQueue[rearrangedSize].studentCount = group.studentCount;
rearrangedSize++;
} else {
rearrangedQueue[rearrangedSize - 1].studentCount += group.studentCount;
}
}
memcpy(groupQueue + front + 1, rearrangedQueue, rearrangedSize * sizeof(Group)); // 更新队列
queueSize = front + 1 + rearrangedSize;
}
front++;
}
// 输出调整次数
printf("%d\n", adjustmentCount);
return 0;
}