题解:洛谷 P8090 Herdle
【题目来源】
洛谷:P8090 [USACO22JAN] Herdle B - 洛谷
【题目描述】
奶牛们发明了一种名为 Herdle 的新型解谜游戏,在牛界引起了轰动。
每天都会有一个新谜题发布供奶牛解决。游戏采用 \(3\times 3\) 方阵的形式表示农场的一块田地,田地的每个方格都由特定品种的奶牛占据。总共只有 \(26\) 种可能的品种,每一种由 \(A\) 到 \(Z\) 中的不同大写字母标识。玩家不会被告知田地中的奶牛品种排列方式——游戏目标是通过一系列猜测确定它们。
每次猜测,奶牛们输入一个 \(3\times 3\) 的大写字母方阵,表示该田地可以用奶牛填充的可能方式。猜测的某些方格可能是正确的。这些方格以绿色高亮显示,让奶牛们知道这些是正确的。猜测的另一些方格可能填入了品种正确但位置错误的奶牛。这些以黄色高亮显示。
黄色高亮显示的方格的数量可以帮助指示某个品种的奶牛数量。例如,假设猜测方阵包含 \(4\) 头品种 \(A\) 的奶牛,而答案方阵包含 \(2\) 只品种 \(A\) 的奶牛,其中没有正确位置上的 \(A\) (即,它们都不应该是绿色的)。在这种情况下,猜测方阵中只有两个 \(A\) 应以黄色高亮显示。更准确地说,如果猜测方阵中有 \(x\) 个特定品种的奶牛,并且 答案方阵中有\(y\le x\) 头该品种奶牛(不包括位置正确而得到绿色高亮显示的奶牛),那么猜测方阵的 \(x\) 头奶牛中只有 \(y\) 头奶牛应该以黄色高亮显示。
给定正确答案的方阵和一个表示对该答案的猜测的方阵,请计算绿色和黄色高亮显示的方格的数量。
【输入】
输入的前 \(3\) 行给定了正确答案的方阵。以下 \(3\) 行表示对该答案的猜测。
【输出】
输出两行。输出的第一行包含应当以绿色高亮显示的方格的数量。输出的第二行包含应当以黄色高亮显示的方格的数量。
【输入样例】
COW
SAY
MOO
WIN
THE
IOI
【输出样例】
1
1
【核心思想】
-
问题分析:给定两个 \(3 \times 3\) 的字母方阵(正确答案和猜测),统计:
- 绿色:位置和内容都正确的方格数
- 黄色:内容正确但位置错误,且受"该品种总数限制"的方格数(即猜测中某品种 \(x\) 个,答案中该品种共 \(y\) 个(不含绿色已匹配的),则最多标记 \(\min(x, y)\) 个黄色,且优先匹配不同位置)
-
算法选择:
- 两遍扫描模拟:第一遍标记所有绿色位置并锁定,第二遍在剩余未锁定位置中按顺序匹配黄色,确保不重复计数且受品种数量限制
-
关键步骤:
- 第一遍:标记绿色:
- 遍历所有 \(3 \times 3 = 9\) 个位置 \((i, j)\)
- 若 \(b[i][j] = a[i][j]\)(猜测与答案同位置同字母):
- \(\text{ans1}++\)(绿色计数)
- 标记 \(\text{fa}[i][j] = 1\) 和 \(\text{fb}[i][j] = 1\)(锁定该位置,后续不再参与黄色匹配)
- 输出绿色数量
- 第二遍:匹配黄色:
- 遍历猜测方阵中所有未锁定位置 \((i, j)\)(\(\text{fb}[i][j] = 0\))
- 对每个未锁定的猜测字母 \(t = b[i][j]\),在答案方阵中寻找未锁定的同字母位置 \((k, l)\)(\(\text{fa}[k][l] = 0\) 且 \(a[k][l] = t\))
- 找到即匹配成功:
- \(\text{ans2}++\)(黄色计数)
- 锁定 \(\text{fb}[i][j] = 1\) 和 \(\text{fa}[k][l] = 1\)(防止重复使用)
- 输出黄色数量
- 第一遍:标记绿色:
-
时间/空间复杂度:
- 时间复杂度:\(O(9 \times 9) = O(1)\),固定 \(3 \times 3\) 方阵
- 空间复杂度:\(O(1)\)
-
两遍扫描匹配的核心思想:
- 绿色优先原则:绿色匹配必须最先处理,因为绿色位置是"正确位置正确品种",这些位置不能参与黄色匹配
- 锁定机制:用 \(\text{fa}\) 和 \(\text{fb}\) 两个标记数组分别锁定答案方阵和猜测方阵中已匹配的位置,确保每个位置只被计数一次
- 品种数量自然限制:由于答案方阵中每个品种只有固定数量,且未锁定位置被逐个匹配,当答案中某品种全部被锁定后,猜测中剩余的该品种自动无法匹配黄色,自然实现 \(y \leq x\) 的限制
- 顺序匹配策略:按位置顺序遍历猜测方阵,遇到可匹配的答案位置立即锁定,保证黄色数量最大化但不超过答案中的实际数量
- 适用于矩阵匹配、位置-内容双重判定、资源有限分配类问题
【解题思路】

【算法标签】
入门 #模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
char a[5][5], b[5][5], t;
int fa[5][5], fb[5][5], ans1=0, ans2=0;
int main()
{
for (int i=1; i<=3; i++) {
for (int j=1; j<=3; j++) {
cin >> a[i][j]; // 输入a矩阵,即正确答案方阵
}
}
for (int i=1; i<=3; i++) {
for (int j=1; j<=3; j++) {
cin >> b[i][j]; // 依次输入b矩阵,即猜测答案
t = b[i][j]; // 使用临时变量t记录
if (t==a[i][j]) { // 如果输入字符与a方阵品种和位置均正确
ans1++; // 绿色方格数自增1
fb[i][j]=1; // 标记a方阵和b方阵中该位置后面不能再使用
fa[i][j]=1;
}
}
}
cout << ans1 << endl; // 输出绿色方格数量
for (int i=1; i<=3; i++) { // 再次遍历b矩阵
for (int j=1; j<=3; j++) {
t = b[i][j]; // 使用临时变量t记录
for (int k=1; k<=3; k++) { // 再双重for循环遍历a矩阵
for (int l=1; l<=3; l++) {
if (fb[i][j]==0 && fa[k][l]==0 && t==a[k][l]) { // 如果a方阵和b方阵该位置可用,且品种相等
ans2++; // 黄色方格数量自增1
fa[k][l]=1; // 标记a方阵和b方阵中该位置后面不能再使用
fb[i][j]=1;
}
}
}
}
}
cout << ans2 << endl; // 输出黄色方格数量
return 0;
}
【运行结果】
COW
SAY
MOO
WIN
THE
IOI
1
1
浙公网安备 33010602011771号