Algorithm 在n个人中查找最多(n/2)-1个说谎者的最快算法
以下是我的设想: 这个问题是用说谎者和说真话的人来描述的,但它在识别复杂系统的哪些组成部分是好的(功能正常)和哪些是错误的方面有实际的应用。假设我们有一个由n人组成的社区,我们知道一个整数tAlgorithm 在n个人中查找最多(n/2)-1个说谎者的最快算法,algorithm,find,compare,Algorithm,Find,Compare,以下是我的设想: 这个问题是用说谎者和说真话的人来描述的,但它在识别复杂系统的哪些组成部分是好的(功能正常)和哪些是错误的方面有实际的应用。假设我们有一个由n人组成的社区,我们知道一个整数tn/2的唯一最大群体。我将把它留给那些容易破坏家庭作业的问题来优化。你说说谎者可能会说真话,也可能会撒谎。在我看来,这使问题变得很困难。我在规范中提供了一个解决方案撒谎者总是撒谎的典型案例 让G成为感兴趣的群体。选择群体中的任意成员,X说。观察询问X的过程“是Y说谎者吗?”如果X和Y都是说真话的人或者都是说谎
最佳算法是什么(最少步数)要找到所有的说谎者?如果你查询所有对,那么说真话的人将显示为大小>n/2的唯一最大群体。我将把它留给那些容易破坏家庭作业的问题来优化。你说说谎者可能会说真话,也可能会撒谎。在我看来,这使问题变得很困难。我在规范中提供了一个解决方案撒谎者总是撒谎的典型案例
让
G
成为感兴趣的群体。选择群体中的任意成员,X
说。观察询问X
的过程“是Y
说谎者吗?”如果X
和Y
都是说真话的人或者都是说谎者,则回答为“是”“否则。因此,通过询问X
“Y是否是说谎者?”对于G
中的每个Y
(不包括X
),您可以找出哪些成员Y
与X
在同一个“团队”中。事实上,说谎者必须多于说谎者,这允许您确定哪个“团队”X
打开,之后很容易识别说谎者。关于这个主题的一篇好论文是莱斯利·兰波特的《拜占庭将军问题》,可在
这不是一个直接的解决方案,但对感兴趣的人来说是一个很好的背景阅读。具有最佳预期运行时间O(n)和优秀常数的随机算法:
多数人决定(这是关键观察!)
我们必须随机选择的预期人数是O(1)(这是这个问题中最重要的部分,因为这可能是家庭作业,我将跳过证明,但提示一个简单的证明:几何分布),这意味着我们将在O(1)*O(n)时间内找到我们的真相讲述者和可靠的来源,然后是另一个O(n)总的来说,O(n)。我的解决方案的伪代码,基本上与Davin的解决方案相同。一个显著的区别是,您只需要最大可能剩余说谎者+1的共识
set unknown = all
set known_true = {}
set known_lie = {}
while known_true.is_empty()
voted_lie = {}
voted_true = {}
truth_votes = 0
lie_votes = 0
to_check = unknown.get(0)
while truth_votes < t - known_lie.size() + 1 && lie_votes < t - known_lie.size() + 1:
checker = unknown.get_next()
if checker.is_liar(to_check):
lie_votes++
voted_lie.add(checker)
else
truth_votes++
voted_true.add(checker)
if truth_votes > t + 1:
unknown.remove(to_check)
known_true.add(to_check)
known_lie.add_all(voted_lie)
unknown.remove_all(voted_lie)
else:
unknown.remove(to_check)
known_lie.add(to_check)
known_lie.add_all(voted_true)
unknown.remove_all(voted_true)
while not unknown.is_empty() && known_liar.size() < t:
to_check = unknown.get(0)
if known_true.get(0).is_liar(to_check):
unknown.remove(to_check)
known_lie.add(to_check)
else
unknown.remove(to_check)
known_true.add(to_check)
set unknown=all
设置已知_true={}
集合已知_lie={}
虽然已知,但为真。是否为空()
投票表决_lie={}
投票结果为_true={}
真理票数=0
lie_票数=0
to_check=未知。获取(0)
当真理投票t+1:
未知。删除(要检查)
已知\u为真。添加(到\u检查)
已知谎言。添加所有谎言(投票谎言)
未知。删除所有(投票表决)
其他:
未知。删除(要检查)
已知谎言。添加(到检查)
已知谎言。添加所有(投票为真)
未知。删除所有(投票为真)
虽然不是未知的。是否为空()&&known\u liar.size()
问题出在哪里?如何识别说谎者?当然,如果说谎者可能说谎,也可能不说谎,那么没有最低的步骤数?你可能不走运,他们可能会在说谎之前任意说出很多次真相。此外,似乎暗示每个人都确切知道说谎者是谁;这是正确的吗?这看起来像是家工作。事实上,这似乎是Cormen等人在《算法导论》第87-88页中练习4-6(VLSI芯片测试)的一个变体。看这个:我只想问,“你是大象吗?”非常有趣的论文。感谢链接!很好的解决方案。你已经证明,说谎者不一定总是撒谎的规定并不会让问题变得更难。如果有n/2-1个说谎者,选择一个说谎者可能是一项困难的任务:假设我们在试图确定单个说谎者时总是选择说谎者。然后整个过程在O(n^2)中,而最优解在O(n)中。@Philip,预期运行时间!你熟悉预期的概率概念吗?