以下是我的情景:
这个问题是关于骗子和真相讲述者的问题,但它在确定复杂系统的哪些组件是好的(正常运行)和哪些是错误方面具有实际应用。假设我们有一个n人的社区,我们知道一个整数t< n / 2,其中有大多数人都是骗子。这并不是说实际上有说谎者,而是说最多只有说谎者。
我认为真相讲述者总是真实而正确,而骗子可能会说出错误答案或正确答案。
我们将通过连续挑选一对人来识别社区中的骗子,(X,Y)说,并问X:Y是骗子吗?回答是“是”或“否”;
查找所有骗子的最佳算法(最小步数)是多少?
答案 0 :(得分:7)
具有O(n)的最佳预期运行时间和优异常数的随机算法:
关键的观察是,如果我们向每个人询问一个人,多数意见必须是正确的(因为大多数真相计票员)。稍微技术性的是,如果我们首先挑选一个非骗子并问别人,假设所有骗子撒谎,我们将达到50-50,那么我们如何决定哪一方说实话?这不是一个问题,因为如果我们首先选择一个非骗子,我们只能达到50-50,所以我们这个人确实是真理出纳员。
我们必须随机选择的预期人数是O(1)(这是这个问题中最可怕的部分,因为它可能是家庭作业,我会跳过证明,但暗示一个简单的证据:几何分布),这意味着我们将在O(1)* O(n)时间内找到我们的真实出纳员和可靠的来源,从那里它是另一个O(n)直到完成。总计,O(n)。
答案 1 :(得分:5)
关于这一主题的一篇好文章是Leslie Lamport的“拜占庭将军问题”,可从以下网站获取 http://research.microsoft.com/en-us/um/people/lamport/pubs/byz.pdf
不是直接的解决方案,而是为感兴趣的人提供良好的背景阅读。
答案 2 :(得分:3)
你说一个骗子可能说实话或撒谎。在我看来,这使问题变得困难。我提供了一个特殊情况下的解决方案,其中一个骗子总是谎言。
让G
成为感兴趣的群体。选择组中的任意成员,X
说。请注意,询问X
“的程序是Y
骗子?”如果X
和Y
都是真相出纳员,或两者都是骗子,则回答为“否”,否则回答为“是”。因此,问X
“是Y
骗子?”对于Y
中的每个G
(X
除外),您可以找出哪些成员Y
与X
位于同一“团队”中。由于必须有比说谎者更多的真相出纳员这一事实,这使您可以识别哪个“团队”X
正在进行,之后识别说谎者很简单。
答案 3 :(得分:1)
我的解决方案的伪代码,与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)
答案 4 :(得分:0)
如果您查询所有对,那么真相出纳员将显示为大小的唯一最大团体&gt; N / 2。我会把它留给那些舒适的破坏性作业问题进行优化。