使用以下原则,您可以获得 90% 的成功:
如果集合中的骗子数量为零,则将该集合分解为大小为 1 的集合,每个集合的骗子数量为零。所以1 3 0
变成1 1 0
和。2 2 0
_3 3 0
如果集合中说谎者的数量等于集合的大小,则将该集合分解为大小为 1 的集合,每个集合中的说谎者数量等于 1。所以2 5 4
变成2 2 1
and3 3 1
和4 4 1
and 5 5 1
。
对于我们拥有的任意两个集合 A 和 B,如果 A 是 B 的子集,则从 B 中删除 A 的所有元素,并从 B 中的骗子数中减去 A 中的骗子数。
我们将使用这些原则来解决您的两个示例问题中较长的一个。首先获取给定的输入,并将它们转换为索引集。
3 4 5 6 7 8 [4]
1 2 3 4 5 6 7 8 9 [6]
1 2 3 4 5 6 7 8 9 10 11 12 13 [9]
5 6 7 8 9 10 11 [5]
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [12]
8 9 10 11 12 13 [5]
4 5 6 7 8 [4]
7 8 9 [2]
10 11 12 13 [3]
7 8 9 10 11 12 13 14 15 16 [7]
14 15 16 17 18 19 [4]
4 5 6 7 8
是 的子集3 4 5 6 7 8
,所以从另一个中减去一个。
3 [1]
1 2 3 4 5 6 7 8 9 [6]
1 2 3 4 5 6 7 8 9 10 11 12 13 [9]
5 6 7 8 9 10 11 [5]
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [12]
8 9 10 11 12 13 [5]
4 5 6 7 8 [4]
7 8 9 [2]
10 11 12 13 [3]
7 8 9 10 11 12 13 14 15 16 [7]
14 15 16 17 18 19 [4]
7 8 9
, 10 11 12 13
, 和14 15 16 17 18 19
都是 的子集4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
,所以减去它们。
3 [1]
1 2 3 4 5 6 7 8 9 [6]
1 2 3 4 5 6 7 8 9 10 11 12 13 [9]
5 6 7 8 9 10 11 [5]
4 5 6 [3]
8 9 10 11 12 13 [5]
4 5 6 7 8 [4]
7 8 9 [2]
10 11 12 13 [3]
7 8 9 10 11 12 13 14 15 16 [7]
14 15 16 17 18 19 [4]
4 5 6
有三个骗子,所以把他们分解成单独的集合。
3 [1]
4 [1]
5 [1]
6 [1]
1 2 3 4 5 6 7 8 9 [6]
1 2 3 4 5 6 7 8 9 10 11 12 13 [9]
5 6 7 8 9 10 11 [5]
8 9 10 11 12 13 [5]
4 5 6 7 8 [4]
7 8 9 [2]
10 11 12 13 [3]
7 8 9 10 11 12 13 14 15 16 [7]
14 15 16 17 18 19 [4]
从包含它们的所有集合中减去 3、4、5 和 6。
3 [1]
4 [1]
5 [1]
6 [1]
1 2 7 8 9 [2]
1 2 7 8 9 10 11 12 13 [5]
7 8 9 10 11 [3]
8 9 10 11 12 13 [5]
7 8 [1]
7 8 9 [2]
10 11 12 13 [3]
7 8 9 10 11 12 13 14 15 16 [7]
14 15 16 17 18 19 [4]
减去7 8
_7 8 9
3 [1]
4 [1]
5 [1]
6 [1]
9 [1]
1 2 7 8 9 [2]
1 2 7 8 9 10 11 12 13 [5]
7 8 9 10 11 [3]
8 9 10 11 12 13 [5]
7 8 [1]
10 11 12 13 [3]
7 8 9 10 11 12 13 14 15 16 [7]
14 15 16 17 18 19 [4]
从包含它的所有集合中减去 9。
3 [1]
4 [1]
5 [1]
6 [1]
9 [1]
1 2 7 8 [1]
1 2 7 8 10 11 12 13 [4]
7 8 10 11 [2]
8 10 11 12 13 [4]
7 8 [1]
10 11 12 13 [3]
7 8 10 11 12 13 14 15 16 [6]
14 15 16 17 18 19 [4]
7 8
从包含两者的任何集合中减去。
3 [1]
4 [1]
5 [1]
6 [1]
9 [1]
1 2 [0]
1 2 10 11 12 13 [3]
10 11 [1]
8 10 11 12 13 [4]
7 8 [1]
10 11 12 13 [3]
10 11 12 13 14 15 16 [5]
14 15 16 17 18 19 [4]
1 2
有 0 个说谎者,因此将它们分解为单独的集合。
1 [0]
2 [0]
3 [1]
4 [1]
5 [1]
6 [1]
9 [1]
1 2 10 11 12 13 [3]
10 11 [1]
8 10 11 12 13 [4]
7 8 [1]
10 11 12 13 [3]
10 11 12 13 14 15 16 [5]
14 15 16 17 18 19 [4]
从包含它们的所有其他集合中减去 1 和 2。
1 [0]
2 [0]
3 [1]
4 [1]
5 [1]
6 [1]
9 [1]
10 11 [1]
8 10 11 12 13 [4]
7 8 [1]
10 11 12 13 [3]
10 11 12 13 14 15 16 [5]
14 15 16 17 18 19 [4]
10 11
从包含两者的任何集合中减去。
1 [0]
2 [0]
3 [1]
4 [1]
5 [1]
6 [1]
9 [1]
10 11 [1]
8 12 13 [3]
7 8 [1]
12 13 [2]
12 13 14 15 16 [4]
14 15 16 17 18 19 [4]
8 12 13
有三个骗子,所以将他们分解成单独的集合,然后从包含它们的任何其他集合中减去它们。
1 [0]
2 [0]
3 [1]
4 [1]
5 [1]
6 [1]
7 [0]
8 [1]
9 [1]
10 11 [1]
12 [1]
13 [1]
14 15 16 [2]
14 15 16 17 18 19 [4]
14 15 16
从中减去14 15 16 17 18 19
。
1 [0]
2 [0]
3 [1]
4 [1]
5 [1]
6 [1]
7 [0]
8 [1]
9 [1]
10 11 [1]
12 [1]
13 [1]
14 15 16 [2]
17 18 19 [2]
我们得到的集合都是相互脱节的。如果我们将它们结合在一起,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [13]
我们可以看到,从 1 到 19 的骗子数量是 13。
这种技术并不能完全解决所有情况下的问题。例如,在您的两个样本输入中较短的一个中,此技术实际上没有任何作用。但是,对于更大的问题,它确实将您的集合分解为更模块化的形式,我希望这会使暴力破解更容易/更快。例如,在更大的样本中,我们将问题空间分解为两种可能性:
1. there are 13 liars among soldiers 1-19, and Soldier 20 is not a liar.
2. there are 13 liars among soldiers 1-19, Soldier 20 is a liar.
我们可以很容易地评估这两种情况,以确定最小的骗子数为 13,最大为 14。这比尝试所有 2^20 的骗子和非骗子组合要快得多。