最新华为OD机试
题目描述
一个人设定一组四码的数字作为谜底,另一方猜。
每猜一个数,出数者就要根据这个数字给出提示,提示以XAYB形式呈现,直到猜中位置。
其中X表示位置正确的数的个数(数字正确且位置正确),而Y表示数字正确而位置不对的数的个数。
例如,当谜底为8123,而猜谜者猜1052时,出题者必须提示0A2B。
例如,当谜底为5637,而猜谜者才4931时,出题者必须提示1A0B。
当前已知N组猜谜者猜的数字与提示,如果答案确定,请输出答案,不确定则输出NA。
输入描述
第一行输入一个正整数,0<N < 100。
接下来N行,每一行包含一个猜测的数字与提示结果。
输出描述
输出最后的答案,答案不确定则输出NA。
示例1
输入
6
4815 1A1B
5716 0A1B
7842 0A1B
4901 0A0B
8585 3A0B
8555 2A1B
1234567
输出
3585
1
解题思路
暴力枚举所有可能的谜底,即0000~9999,然后用每一个谜底去匹配输入的猜测。如果当前谜底与输入的猜测产生的提示符合预期,则说明该谜底是可行的。如果某个谜底可以符合所有输入的猜测,那么该谜底就是题解。如果暴力枚举出来的所有谜底中只有一个可行的谜底,那么该谜底就是题解,否则本题无解,返回NA。
由于需要验证0000~9999这一万个可能的谜底,而每个谜底最多需要验证100个输入的猜测数字,因此该算法非常容易超时。为了优化算法,我们可以对输入的猜测进行剪枝处理。例如,当输入的猜测提示为0A0B时,我们可以排除所有包含输入数字的谜底,因为这些谜底与输入数字的位置和数字都不匹配。同样地,当输入的猜测提示为0A时,我们可以排除所有包含输入数字的位置的谜底,因为这些谜底与输入数字的位置不匹配。通过对输入的猜测进行剪枝处理,我们可以大大减少需要验证的谜底数量,从而提高算法效率。
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 输入猜测的次数
// 存储所有猜测的数字和提示结果
List<String[]> guessInfos = new ArrayList<>();
for (int i = 0; i < n; i++) {
String guessNum = scanner.next(); // 输入猜测的数字
String guessResult = scanner.next(); // 输入猜测的结果
guessInfos.add(new String[]{
guessNum, guessResult}); // 将猜测的数字和结果存入列表中
}
int validCount = 0; // 记录符合条件的答案数量
String validAnswer = ""; // 存储符合条件的答案
// 遍历所有可能的四位数
for (int num = 0; num <= 9999; num++) {
String answer = String.format("%04d", num); // 将数字格式化为四位数字符串
boolean isValid = true; // 标记当前答案是否有效
// 遍历每个猜测的数字和结果
for (String[] guessInfo : guessInfos) {
String guess = guessInfo[0]; // 获取猜测的数字
String expectResult = guessInfo[1]; // 获取猜测的结果
int countA = 0; // 记录数字和位置都正确的个数
int countB = 0; // 记录数字正确但位置不正确的个数
int[] answerArr = new int[10]; // 存储答案中每个数字出现的次数
int[] guessArr = new int[10]; // 存储猜测中每个数字出现的次数
// 遍历每个位置
for (int i = 0; i < guess.length(); i++) {
int c1Int = guess.charAt(i) - '0'; // 获取猜测中该位置上的数字
int c2Int = answer.charAt(i) - '0'; // 获取答案中该位置上的数字
if (c1Int == c2Int) {
countA++; // 如果数字和位置都正确,countA+1
} else {
guessArr[c1Int]++; // 在 guessArr 中记录该数字出现的次数
answerArr[c2Int]++; // 在 answerArr 中记录该数字出现的次数
}
}
for (int i = 0; i < 10; i++) {
countB += Math.min(answerArr[i], guessArr[i]); // 计算数字正确但位置不正确的个数
}
String realResult = countA + "A" + countB + "B"; // 根据猜测和答案计算真实结果
if (!realResult.equals(expectResult)) {
isValid =

最低0.47元/天 解锁文章
5570

被折叠的 条评论
为什么被折叠?



