前言
“实战算法”是本专栏的第三个部分,本篇博文是第三篇博文,主要讲解百度笔试题——宝箱怪——的解法,如有需要,可:
一、题目描述
宝箱怪是游戏中常见的一种怪物,它们伪装成普通的宝箱,并在被玩家打开时攻击玩家。假设你操控的游戏角色身处一个放着N个宝箱的房间,每个宝箱或者是普通的宝箱,或者是宝箱怪。每个宝箱上都贴着一张字条,字条上写着以下两种信息中的一种:
①第x个宝箱是普通宝箱;
②第x个宝箱是宝箱怪。
其中普通宝箱上的信息一定是真的,而宝箱怪上的信息可能是假的,那么根据这些信息,有多少个宝箱一定是普通宝箱,又有多少个宝箱一定是宝箱怪?
-
输入描述
第一行包含一个整数N
,1≤N≤10^5
.
接下来N
行,第i
行包含两个整数t
和x
,1≤t≤2
,1≤x≤N
. 若t=1
,则第i
个宝箱上的信息为:第x
个宝箱是普通宝箱;若t=2
,则第i
个宝箱上的信息为:第x
个宝箱是宝箱怪。 -
输出描述
输出两个以空格隔开的整数,第一个整数表示可以确定为普通宝箱的宝箱数量,第二个整数表示可以确定为宝箱怪的宝箱数量。 -
样例输入
3
1 2
2 1
1 3 -
样例输出
0 1 -
Hint
每个宝箱都可能是宝箱怪,其中第一个宝箱一定是宝箱怪。
二、解题思路
这个题主要在于如何判定一个宝箱是宝箱怪还是普通宝箱的问题。因为只有宝箱怪可能说假话,因此只有当一个宝箱说另一个确定是宝箱怪的宝箱是普通宝箱时,才能证实前者是一个宝箱怪。
因为题目中说第一个宝箱一定是个宝箱怪,因此,通过多次迭代,第一次就找说第一个宝箱是普通宝箱的宝箱,他们一定是宝箱怪;第二次再找说在第一轮中排查出的宝箱怪是普通宝箱的宝箱……依次类推,直到排查出所有的宝箱怪。
而普通宝箱是没有办法确定的,因此一定是0.
三、代码实现
- 计算方法
public static int[] Judge(List<Integer[]> numbers) {
HashSet<Integer> mimics = new HashSet<>();
mimics.add(1);
boolean remainsMonster = true;
while (remainsMonster) {
for (int i = 1; i < numbers.size(); i++) {
Integer[] number = numbers.get(i);
if (number[0] == 1 && mimics.contains(number[1])) {
mimics.add(i);
}
}
remainsMonster = false;
for (int i = 1; i < numbers.size(); i++) {
Integer[] number = numbers.get(i);
if (number[0] == 1 && mimics.contains(number[1]) && !mimics.contains(i)) {
remainsMonster = true;
break;
}
}
}
return new int[]{0, mimics.size()};
}
说明: 因为需要判断需不需要进行下一次迭代,最后的for循环是必须的。
- 主方法(包括输入输出)
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int count = scanner.nextInt();
List<Integer[]> numbers = new ArrayList<>();
numbers.add(null);
scanner.nextLine();
int counter = 0;
while (counter < count) {
String line = scanner.nextLine().trim();
String[] valueString = line.split(" ");
Integer[] valueArray = new Integer[2];
valueArray[0] = Integer.parseInt(valueString[0]);
valueArray[1] = Integer.parseInt(valueString[1]);
numbers.add(valueArray);
counter++;
}
int[] result = Judge(numbers);
System.out.println(result[0] + " " + result[1]);
}
后记
这个题目思路上想通了之后,代码方面中规中矩,没有什么难度