AtCoder Weekday Contest 0007 Beta题解(AWC 0007 Beta A-E)
A - Selection of Delivery Trucks
【题目来源】
AtCoder:A - Selection of Delivery Trucks
【题目描述】
Takahashi is a delivery planning manager at a shipping company. He needs to select exactly \(1\) truck out of \(N\) delivery trucks and assign it to a delivery task.
高桥是一家货运公司的送货路线规划经理。他需要从 \(N\) 辆送货卡车中恰好选择 \(1\) 辆,并将其分配至一项送货任务。
Each truck \(i\) (\(1 \leq i \leq N\)) has a fuel efficiency coefficient \(E_i\). A truck with a larger fuel efficiency coefficient consumes more fuel to travel the same distance.
每辆卡车 \(i\)(\(1 ≤ i ≤ N\))具有一个燃油效率系数 \(E_i\)。燃油效率系数越大的卡车,行驶相同距离消耗的燃料越多。
The delivery route consists of \(M\) segments, and the distance of the \(j\)-th segment (\(1 \leq j \leq M\)) is \(C_j\). The selected truck will travel all \(M\) segments. The fuel consumed when truck \(i\) travels the \(j\)-th segment is \(E_i \times C_j\).
送货路线包含 \(M\) 个路段,第 \(j\) 个路段(\(1 ≤ j ≤ M\))的距离为 \(C_j\)。被选中的卡车将行驶全部 \(M\) 个路段。当卡车 \(i\) 行驶第 \(j\) 个路段时,消耗的燃料为 \(E_i × C_j\)。
The total fuel consumption when truck \(i\) is selected is
当选中卡车 \(i\) 时,总燃料消耗量为
Find the minimum total fuel consumption when exactly \(1\) truck is chosen from the \(N\) trucks to minimize the total fuel consumption.
求从 \(N\) 辆卡车中恰好选择 \(1\) 辆以最小化总燃料消耗量时的最小总燃料消耗量。
【输入】
\(N\) \(M\)
\(E_1\) \(E_2\) \(\ldots\) \(E_N\)
\(C_1\) \(C_2\) \(\ldots\) \(C_M\)
- The first line contains an integer \(N\) representing the number of trucks and an integer \(M\) representing the number of segments in the delivery route, separated by a space.
- The second line contains \(N\) integers \(E_1, E_2, \ldots, E_N\) representing the fuel efficiency coefficients of each truck, separated by spaces.
- The third line contains \(M\) integers \(C_1, C_2, \ldots, C_M\) representing the distance of each segment, separated by spaces.
【输出】
Print the minimum fuel consumption on a single line.
【输入样例】
3 4
5 3 7
2 4 1 3
【输出样例】
30
【解题思路】

【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m; // n: 第一个数组长度,m: 第二个数组长度
signed main()
{
cin >> n >> m; // 读入两个数组的长度
int minn = 1e9; // 初始化最小值,用于存储第一个数组的最小值
for (int i = 1; i <= n; i++)
{
int x;
cin >> x; // 读入第一个数组的元素
minn = min(minn, x); // 更新最小值
}
int sum = 0; // 初始化总和,用于存储第二个数组的和
for (int i = 1; i <= m; i++)
{
int x;
cin >> x; // 读入第二个数组的元素
sum += x; // 累加总和
}
cout << minn * sum << endl; // 输出第一个数组最小值与第二个数组总和的乘积
return 0;
}
【运行结果】
3 4
5 3 7
2 4 1 3
30
B - Laboratories That Can Collaborate
【题目来源】
AtCoder:B - Laboratories That Can Collaborate
【题目描述】
Takahashi works at the university's research support center. The university has \(N\) laboratories, and each laboratory is working on several research themes. Laboratory \(i\) (\(1 \leq i \leq N\)) is working on \(M_i\) research themes, each represented by a string of lowercase English letters \(W_{i,1}, W_{i,2}, \ldots, W_{i,M_i}\). Note that the same research theme does not appear more than once within the same laboratory.
高桥在大学的研究支持中心工作。该大学有 \(N\) 个实验室,每个实验室正在进行若干研究课题。实验室 \(i\)(\(1 ≤ i ≤ N\))正在进行 \(M_i\) 个研究课题,每个课题用一个小写英文字母字符串 \(W_{i,1}, W_{i,2}, \ldots, W_{i,M_i}\) 表示。注意,同一研究课题不会在同一实验室内出现超过一次。
To promote collaborative research, the university has decided to investigate pairs of laboratories that are "eligible for collaboration." Let \(S_i = \{W_{i,1}, W_{i,2}, \ldots, W_{i,M_i}\}\) be the set of research themes that laboratory \(i\) is working on. Two laboratories \(i, j\) (\(i \neq j\)) are said to be "eligible for collaboration" if the number of research themes common to both \(S_i\) and \(S_j\) is at least \(K\), that is, \(|S_i \cap S_j| \geq K\) holds. Here, whether two research themes are identical is determined by whether their representing strings match exactly.
为促进合作研究,该大学决定调查那些"具备合作资格"的实验室对。令 \(S_i = {W_{i,1}, W_{i,2}, \ldots, W_{i,M_i}}\) 表示实验室 \(i\) 正在进行的研究课题集合。两个实验室 \(i, j\) (\(i \neq j\)) 被称为"具备合作资格",如果它们共同的研究课题数量至少为 \(K\),即满足 \(|S_i \cap S_j| \geq K\)。这里,两个研究课题是否相同取决于它们的表示字符串是否精确匹配。
Takahashi has the list of research themes each laboratory is working on. Based on this information, find the number of pairs of laboratories that are "eligible for collaboration." Note that the pair of laboratory \(i\) and laboratory \(j\) is considered the same as the pair of laboratory \(j\) and laboratory \(i\). Count the number of pairs \((i, j)\) satisfying \(1 \leq i < j \leq N\) that meet the condition.
高桥拥有每个实验室正在进行的研究课题列表。基于此信息,求"具备合作资格"的实验室对的数量。注意,实验室 \(i\) 与实验室 \(j\) 组成的对被视为与实验室 \(j\) 与实验室 \(i\) 组成的对相同。统计满足条件且满足 \(1 ≤ i < j ≤ N\) 的对 \((i, j)\) 的数量。
【输入】
The input is given from standard input in the following format.
\(N\) \(K\)
\(M_1\)
\(W_{1,1}\) \(W_{1,2}\) \(\ldots\) \(W_{1,M_1}\)
\(M_2\)
\(W_{2,1}\) \(W_{2,2}\) \(\ldots\) \(W_{2,M_2}\)
\(\vdots\)
\(M_N\)
\(W_{N,1}\) \(W_{N,2}\) \(\ldots\) \(W_{N,M_N}\)
The first line contains the number of laboratories \(N\) and the threshold \(K\) used for determining "eligibility for collaboration," separated by a space.
Then, for each laboratory \(i\) (\(i = 1, 2, \ldots, N\)), the following \(2\) lines are given in order:
- The first line contains the number of research themes \(M_i\) that laboratory \(i\) is working on.
- The second line contains the \(M_i\) strings \(W_{i,1}, W_{i,2}, \ldots, W_{i,M_i}\) representing the research themes of laboratory \(i\), separated by spaces.
【输出】
Output the number of pairs of laboratories that are "eligible for collaboration" in a single line.
【输入样例】
3 2
3
ai ml data
4
ml data web security
2
ai ml
【输出样例】
2
【解题思路】

【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 505, M = 55;
int n, k, m[N], ans; // n: 集合数量,k: 阈值,m[i]: 第i个集合的大小,ans: 结果计数
string a[N][M]; // a[i][j]: 第i个集合的第j个元素
int main()
{
cin >> n >> k; // 读入集合数量和阈值
for (int i = 1; i <= n; i++)
{
cin >> m[i]; // 读入第i个集合的元素数量
for (int j = 1; j <= m[i]; j++)
{
cin >> a[i][j]; // 读入第i个集合的第j个元素
}
}
// 遍历所有集合对(i, j),其中i<j
for (int i = 1; i < n; i++)
{
for (int j = i + 1; j <= n; j++)
{
int cnt = 0; // 记录两个集合的共同元素个数
// 统计集合i和集合j的共同元素个数
for (int kk = 1; kk <= m[i]; kk++) // 注意:这里使用kk避免与变量k重名
{
for (int l = 1; l <= m[j]; l++)
{
if (a[i][kk] == a[j][l]) // 如果元素相同
{
cnt++; // 计数加1
}
}
}
// 如果共同元素个数达到阈值k
if (cnt >= k)
{
ans++; // 结果计数加1
}
}
}
cout << ans << endl; // 输出满足条件的集合对数量
return 0;
}
【运行结果】
3 2
3
ai ml data
4
ml data web security
2
ai ml
2
C - Group Knockout Battle
【题目来源】
AtCoder:C - Group Knockout Battle
【题目描述】
Takahashi is hosting a quiz tournament in which \(N\) students participate.
高桥正在举办一场有 \(N\) 名学生参加的问答锦标赛。
Each student is assigned a student ID number from \(1\) to \(N\), and student \(i\) has a quiz skill level of \(A_i\).
每名学生分配有一个从 \(1\) 到 \(N\) 的学生 ID 编号,且学生 \(i\) 具有问答技能水平 \(A_i\)。
At the start of the tournament, all \(N\) students remain, and "rounds" are repeated according to the following rules:
锦标赛开始时,所有 \(N\) 名学生均在场,并按以下规则重复进行"轮次":
- Arrange the currently remaining students in ascending order of their student ID numbers, and divide them into groups of \(K\) from the front. That is, the 1st through \(K\)-th students in the arranged sequence form group 1, the \((K{+}1)\)-th through \(2K\)-th form group 2, and so on. If the last group has fewer than \(K\) students, it remains as a single group with that number of students.
将当前在场的学生按其学生 ID 编号升序排列,并从前往后每 \(K\) 人分为一组。也就是说,排列序列中第 \(1\) 至第 \(K\) 名学生组成第 \(1\) 组,第 \((K+1)\) 至第 \(2K\) 名组成第 \(2\) 组,依此类推。如果最后一组的学生少于 \(K\) 人,则将其保留为一个人数不足 \(K\) 的独立组。 - For each group, only the \(1\) student with the highest skill level in that group survives. If there are multiple students with the highest skill level, the one with the smallest student ID number among them survives. (If a group has only \(1\) student, that student survives as is.)
对于每个组,只有该组中技能水平最高的 \(1\) 名学生能晋级。如果有多名学生具有相同的最高技能水平,则其中学生 ID 编号最小者晋级。(如果一个组仅有 \(1\) 名学生,则该名学生直接晋级。) - If only \(1\) student remains, that student is declared the champion and the tournament ends. If \(2\) or more students remain, only the surviving students are kept and we return to step 1 to conduct the next round.
如果只剩下 \(1\) 名学生,则该名学生被宣布为冠军,锦标赛结束。如果剩下 \(2\) 名或更多学生,则仅保留晋级的学生,并返回步骤 \(1\) 进行下一轮。
In each round, there are at least \(2\) remaining students, and since \(K \geq 2\), at least one group contains \(2\) or more students, so the number of remaining students strictly decreases with each round. Therefore, the tournament ends after a finite number of rounds.
在每一轮中,至少还有 \(2\) 名学生,且由于 \(K ≥ 2\),至少有一个组包含 \(2\) 名或更多学生,因此剩余学生人数每轮严格减少。所以,锦标赛会在有限轮后结束。
Determine the student ID number of the student who ultimately wins the tournament.
确定最终赢得锦标赛的学生的学生 ID 编号。
【输入】
\(N\) \(K\)
\(A_1\) \(A_2\) \(\ldots\) \(A_N\)
- The first line contains the integer \(N\) representing the number of students and the integer \(K\) representing the maximum number of students per group, separated by a space.
- The second line contains the integers \(A_1, A_2, \ldots, A_N\) representing each student's skill level, separated by spaces.
【输出】
Print the student ID number of the winning student on a single line.
【输入样例】
6 2
3 1 4 1 5 9
【输出样例】
6
【解题思路】

【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 500005;
int n, k; // n: 元素数量,k: 题目中未使用
struct Node
{
int x, id; // x: 元素值,id: 元素原始位置
}a[N];
// 比较函数:先按x值降序排列,如果x值相同则按id升序排列
bool cmp(Node x, Node y)
{
if (x.x != y.x)
{
return x.x > y.x;
}
return x.id < y.id;
}
int main()
{
cin >> n >> k; // 读入元素数量n和k(k在代码中未使用)
for (int i = 1; i <= n; i++)
{
cin >> a[i].x; // 读入第i个元素的值
a[i].id = i; // 记录元素的原始位置
}
// 按照比较函数排序
sort(a + 1, a + n + 1, cmp);
// 输出排序后第一个元素的原始位置(即值最大,如果值相同则位置最小)
cout << a[1].id << endl;
return 0;
}
【运行结果】
6 2
3 1 4 1 5 9
6
D - Investigation of Overlapping Advertisement Areas
【题目来源】
AtCoder:D - Investigation of Overlapping Advertisement Areas3
【题目描述】
Takahashi and Aoki are each planning to post advertisements on an \(N \times N\) grid bulletin board. Each cell of the bulletin board is represented by coordinates \((r, c)\) (\(1 \leq r \leq N\), \(1 \leq c \leq N\)), where \(r\) is the row number counted from the top and \(c\) is the column number counted from the left.
高桥和青木各自计划在一块 \(N × N\) 的网格公告板上发布广告。公告板的每个单元格由坐标 \((r, c)\) 表示(\(1 ≤ r ≤ N, 1 ≤ c ≤ N\)),其中 \(r\) 是从上往下计数的行号,\(c\) 是从左往右计数的列号。
Takahashi plans to post \(A\) rectangular advertisements, and Aoki plans to post \(B\) rectangular advertisements on the bulletin board. Each advertisement covers a rectangular region specified by its top-left cell \((r_1, c_1)\) and bottom-right cell \((r_2, c_2)\). That is, all cells \((r, c)\) satisfying \(r_1 \leq r \leq r_2\) and \(c_1 \leq c \leq c_2\) are covered.
高桥计划张贴 \(A\) 个矩形广告,青木计划在公告板上张贴 \(B\) 个矩形广告。每个广告覆盖一个由其左上角单元格 \((r_1, c_1)\) 和右下角单元格 \((r_2, c_2)\) 指定的矩形区域。也就是说,所有满足 \(r_1 ≤ r ≤ r_2\) 且 \(c_1 ≤ c ≤ c_2\) 的单元格 \((r, c)\) 均被覆盖。
The bulletin board manager is concerned that cells covered by both Takahashi's and Aoki's advertisements will look unsightly, and wants to know the total number of such overlapping cells in advance.
公告板管理员担心被高桥和青木的广告同时覆盖的单元格会显得不美观,因此希望提前知道这类重叠单元格的总数。
Find the number of cells that are covered by at least one of Takahashi's advertisements and also covered by at least one of Aoki's advertisements. Even if the same cell is covered by multiple combinations of advertisements, it is counted only once.
求至少被高桥的一个广告覆盖且同时至少被青木的一个广告覆盖的单元格数量。即使同一单元格被多组广告组合覆盖,也仅计数一次。
【输入】
\(N\) \(A\) \(B\)
\(r_{1,1}\) \(c_{1,1}\) \(r_{2,1}\) \(c_{2,1}\)
\(r_{1,2}\) \(c_{1,2}\) \(r_{2,2}\) \(c_{2,2}\)
:
\(r_{1,A}\) \(c_{1,A}\) \(r_{2,A}\) \(c_{2,A}\)
\(r'_{1,1}\) \(c'_{1,1}\) \(r'_{2,1}\) \(c'_{2,1}\)
\(r'_{1,2}\) \(c'_{1,2}\) \(r'_{2,2}\) \(c'_{2,2}\)
:
\(r'_{1,B}\) \(c'_{1,B}\) \(r'_{2,B}\) \(c'_{2,B}\)
- The first line contains the board size \(N\), the number of Takahashi's advertisements \(A\), and the number of Aoki's advertisements \(B\), separated by spaces.
- The following \(A\) lines each describe one of Takahashi's advertisements.
- The \(i\)-th advertisement (\(1 \leq i \leq A\)) is given as four space-separated integers representing the top-left cell \((r_{1,i}, c_{1,i})\) and the bottom-right cell \((r_{2,i}, c_{2,i})\).
- The following \(B\) lines each describe one of Aoki's advertisements.
- The \(j\)-th advertisement (\(1 \leq j \leq B\)) is given as four space-separated integers representing the top-left cell \((r'_{1,j}, c'_{1,j})\) and the bottom-right cell \((r'_{2,j}, c'_{2,j})\).
【输出】
Output the number of cells where Takahashi's advertisements and Aoki's advertisements overlap, on a single line.
【输入样例】
5 1 1
1 1 3 3
2 2 4 4
【输出样例】
4
【解题思路】

【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
int g[N][N], h[N][N]; // g: 第一个涂色区域的网格,h: 第二个涂色区域的网格
int n, a, b, ans; // n: 网格大小,a: 第一个区域的矩形数量,b: 第二个区域的矩形数量,ans: 重叠区域数量
int main()
{
cin >> n >> a >> b; // 读入网格大小和两个区域的矩形数量
// 处理第一个涂色区域
for (int i = 1; i <= a; i++)
{
int r1, c1, r2, c2; // 矩形的左上角(r1,c1)和右下角(r2,c2)
cin >> r1 >> c1 >> r2 >> c2; // 读入矩形坐标
for (int r = r1; r <= r2; r++) // 遍历矩形所在的行
{
for (int c = c1; c <= c2; c++) // 遍历矩形所在的列
{
g[r][c] = 1; // 标记第一个涂色区域
}
}
}
// 处理第二个涂色区域
for (int i = 1; i <= b; i++)
{
int r1, c1, r2, c2; // 矩形的左上角(r1,c1)和右下角(r2,c2)
cin >> r1 >> c1 >> r2 >> c2; // 读入矩形坐标
for (int r = r1; r <= r2; r++) // 遍历矩形所在的行
{
for (int c = c1; c <= c2; c++) // 遍历矩形所在的列
{
h[r][c] = 1; // 标记第二个涂色区域
}
}
}
// 统计两个区域重叠的格子数量
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (g[i][j] == 1 && h[i][j] == 1) // 如果两个区域都覆盖了这个格子
{
ans++; // 重叠格子数量加1
}
}
}
cout << ans << endl; // 输出重叠格子数量
return 0;
}
【运行结果】
5 1 1
1 1 3 3
2 2 4 4
4
E - Warehouse Robot Delivery
【题目来源】
AtCoder:E - Warehouse Robot Delivery
【题目描述】
Takahashi is a programmer for delivery robots working in a large warehouse.
高桥是在一个大型仓库工作的送货机器人程序员。
The warehouse floor is divided into an \(N \times N\) grid. The cell in the \(r\)-th row from the top \((1 \leq r \leq N)\) and the \(c\)-th column from the left \((1 \leq c \leq N)\) is assigned the number \((r-1) \times N + c\). That is, the cells are numbered \(1, 2, \ldots, N\) from left to right in row \(1\), then \(N+1, N+2, \ldots, 2N\) from left to right in row \(2\), and so on. There are no walls or obstacles on the grid, and all cells are passable.
仓库地面被划分成一个 \(N × N\) 的网格。从上往下第 \(r\) 行(\(1 ≤ r ≤ N\))和从左往右第 \(c\) 列(\(1 ≤ c ≤ N\))的单元格被赋予编号 \((r-1) × N + c\)。也就是说,单元格的编号方式为:在第 \(1\) 行中从左到右编号 \(1, 2, …, N\),然后在第 2 行中从左到右编号 \(N+1, N+2, …, 2N\),依此类推。网格上没有墙壁或障碍物,所有单元格均可通行。
The delivery robot is currently waiting at cell \(S\). Takahashi needs to move the robot to the shipping area at cell \(T\). \(S\) and \(T\) are different cells. In one move, the robot can move one cell to an adjacent cell in one of the four directions (up, down, left, right). However, the robot cannot move outside the grid.
送货机器人当前在单元格 \(S\) 处等待。高桥需要将机器人移动到位于单元格 \(T\) 的发货区。\(S\) 和 \(T\) 是不同的单元格。在单次移动中,机器人可以向四个方向(上、下、左、右)之一移动到相邻的单元格。但机器人不能移动到网格外。
During its movement, the robot must collect packages from \(M\) designated shelves. The cell numbers \(P_1, P_2, \ldots, P_M\) where the shelves with packages to collect are located are given. These \(M\) cells may be visited in any order, but all of them must be visited at least once before reaching cell \(T\). Note that passing through the same cell multiple times during movement is allowed.
在移动过程中,机器人必须从 \(M\) 个指定的货架上收取包裹。给出了存放待收取包裹的货架所在的单元格编号 \(P_1, P_2, …, P_M\)。这 \(M\) 个单元格可以以任意顺序访问,但在到达单元格 \(T\) 之前,所有单元格都必须至少访问一次。注意,允许在移动过程中多次经过同一个单元格。
Find the minimum number of moves required for the robot to start from cell \(S\), visit all \(M\) designated cells, and reach cell \(T\). Here, the number of moves refers to the total number of times the robot moves to an adjacent cell.
求机器人从单元格 \(S\) 出发,访问所有 \(M\) 个指定单元格,并到达单元格 \(T\) 所需的最少移动次数。此处,移动次数指机器人移动到相邻单元格的总次数。
【输入】
\(N\) \(M\)
\(S\) \(T\)
\(P_1\) \(P_2\) \(\cdots\) \(P_M\)
- The first line contains an integer \(N\) representing the side length of the grid and an integer \(M\) representing the number of cells to visit, separated by a space.
- The second line contains an integer \(S\) representing the starting cell number and an integer \(T\) representing the destination cell number, separated by a space.
- The third line contains integers \(P_1, P_2, \ldots, P_M\) representing the cell numbers to visit, separated by spaces. If \(M = 0\), the third line is not given.
【输出】
Print in one line the minimum number of moves required for the robot to start from cell \(S\), visit all designated cells, and reach cell \(T\).
【输入样例】
3 2
1 9
5 3
【输出样例】
6
【解题思路】

【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 20, M = 1 << 17;
#define int long long
typedef pair<int, int> PII;
int n, m, s, t; // n: 网格大小,m: 中间点数,s: 起点,t: 终点
PII p[N]; // 存储所有点的坐标,包括起点、中间点和终点
int dp[M][N]; // dp[state][j]: 访问状态为state,最后到达点j的最小距离
// 将编号转换为网格坐标
PII getpos(int t)
{
int x = (t + n - 1) / n; // 行号
int y = t % n; // 列号
if (y == 0)
{
y = n; // 处理余数为0的情况
}
return {x, y};
}
// 计算两点之间的曼哈顿距离
int getdist(int x, int y)
{
return abs(p[x].first - p[y].first) + abs(p[x].second - p[y].second);
}
signed main()
{
cin >> n >> m >> s >> t; // 读入网格大小、中间点数、起点、终点
p[0] = getpos(s); // 起点存储在p[0]
for (int i = 1; i <= m; i++)
{
int x;
cin >> x; // 读入中间点编号
p[i] = getpos(x); // 转换为坐标
}
p[++m] = getpos(t); // 终点存储在p[m+1]
memset(dp, 0x3f, sizeof(dp)); // 初始化dp数组为无穷大
// 初始化dp:从起点直接到每个点的距离
for (int i = 1; i <= m; i++)
{
dp[1 << (i - 1)][i] = getdist(0, i);
}
// 状态压缩DP
for (int i = 1; i < (1 << m); i++) // 遍历所有状态
{
for (int j = 1; j <= m; j++) // 遍历当前最后到达的点
{
if (i & (1 << (j - 1))) // 如果状态i中包含点j
{
for (int k = 1; k <= m; k++) // 遍历上一个点
{
if (k != j && (i & (1 << (k - 1)))) // 如果状态i中包含点k,且k不等于j
{
dp[i][j] = min(dp[i][j], dp[i ^ (1 << (j - 1))][k] + getdist(k, j)); // 从当前状态中移除最后一个点j,得到到达j之前的状态,再加上k到j的距离
}
}
}
}
}
cout << dp[(1 << m) - 1][m] << endl; // 输出访问所有点最后到达终点的最短距离
return 0;
}
【运行结果】
3 2
1 9
5 3
6
浙公网安备 33010602011771号