先逐格统计绿色,再用每个字母在答案和猜测中的较小频次求总高亮数并扣出黄色。
OJ: usaco
题目 ID: 1179
难度:入门
标签:模拟计数字符串
日期: 2026-07-11 13:19
题意
给定一个正确答案的
如果某个位置的字母完全正确,这个格子标绿色;如果某个字母在答案中出现过,但猜测的位置不正确,这个格子可能标黄色。
要求输出绿色数量和黄色数量。
思路
暴力想法
一个直观做法是:先把所有位置相同的格子标成绿色;再对每个没有变绿的猜测格,找一个还没被使用过、字母相同的答案格,把它标成黄色。
这个做法直接模拟题意:
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-11 13:19
* update_at: 2026-07-11 13:23
*/
// brute.cpp:小数据暴力解,用来帮助理解题意并辅助对拍。
#include <bits/stdc++.h>
using namespace std;
string answer_grid[3];
string guess_grid[3];
bool answer_used[3][3];
bool guess_green[3][3];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
for (int i = 0; i < 3; i++) {
cin >> answer_grid[i];
}
for (int i = 0; i < 3; i++) {
cin >> guess_grid[i];
}
int green = 0;
int yellow = 0;
// 先处理位置完全相同的绿色格子。
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (answer_grid[i][j] == guess_grid[i][j]) {
green++;
answer_used[i][j] = true;
guess_green[i][j] = true;
}
}
}
// 再给每个没有变绿的猜测格,找一个还没使用过的同字母答案格。
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (guess_green[i][j]) {
continue;
}
bool found = false;
for (int x = 0; x < 3 && !found; x++) {
for (int y = 0; y < 3 && !found; y++) {
if (!answer_used[x][y] && answer_grid[x][y] == guess_grid[i][j]) {
answer_used[x][y] = true;
yellow++;
found = true;
}
}
}
}
}
cout << green << '\n';
cout << yellow << '\n';
return 0;
}频次计数
官方解析的关键是把每个字母独立考虑。
对于某个字母 ch,假设它在答案中出现 x 次,在猜测中出现 y 次,那么这个字母最多只能贡献:
个高亮格子。这里的高亮包含绿色和黄色。
所以:
text
总高亮数 = 所有字母 min(答案频次, 猜测频次) 的和
黄色数 = 总高亮数 - 绿色数绿色数只需要逐格比较统计。
代码
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-11 13:19
* update_at: 2026-07-11 13:23
*/
#include <bits/stdc++.h>
using namespace std;
string answer_grid[3];
string guess_grid[3];
int cnt_answer[26];
int cnt_guess[26];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
for (int i = 0; i < 3; i++) {
cin >> answer_grid[i];
}
for (int i = 0; i < 3; i++) {
cin >> guess_grid[i];
}
int green = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
char a = answer_grid[i][j];
char b = guess_grid[i][j];
if (a == b) {
green++;
}
cnt_answer[a - 'A']++;
cnt_guess[b - 'A']++;
}
}
int total_highlight = 0;
for (int i = 0; i < 26; i++) {
total_highlight += min(cnt_answer[i], cnt_guess[i]);
}
int yellow = total_highlight - green;
cout << green << '\n';
cout << yellow << '\n';
return 0;
}复杂度
方阵大小固定为
使用两个长度为 26 的频次数组,空间复杂度为
总结
这题最容易出错的地方是重复字母。
不要把“猜测里字母存在但位置不同”直接全算成黄色,而要用答案和猜测中该字母出现次数的较小值限制总高亮数量。