Algorithm 在尽可能少的步骤中找到运动目标的算法
我正试图解决以下问题: 一排有6个杯子(比如编号1到6)。其中一个杯子下面有一个球(我不知道是哪一个)。我可以举起一个杯子,看看球是否在那里。如果是,我赢了。如果不是,球将从其当前位置移动到一个杯上,直接向左或向右移动(因此从杯4移动到杯3或杯5。从杯6移动到杯5)。球必须移动,不能停留在原地 问题是:如果你使用最佳策略,经过多少次“杯托”后,你会知道球的位置 目前,我已经想出了一个策略,最坏的情况是6部电梯。请注意,不需要进行最后的举重,“证明”球的位置。我的问题是:是否有一种算法具有更好的“最坏情况”?如果不是,我如何证明这是最好的算法 我目前的战略。我们假设球在一开始是在一个均匀的杯子下(2,4或6)。我的最坏情况的一步一步如下 提起1:提起2号杯子。球不在那里。根据我们的假设,球将移动到一个奇数杯,但它不可能移动到第1杯(因为它必须起源于第2杯,但它不在那里) 提起2:提起3号杯子。球不在那里。我不可能在1岁以下(见上图),也不可能在3岁以下,假设是在一个奇怪的杯子下。这意味着它现在位于杯5下,因此必须移动到杯4或杯6 举起3号:举起4号杯子,球不在那里。这意味着它必须移动到第6个杯子,所以下一步它必须移动到第5个杯子 举起4:举起5号杯子,球不在那里。这是唯一剩下的可能性,所以我们错误地猜测它是在一个均匀的杯子下开始的。因此,它现在处于某个偶数杯之下,下一步将移动到一个奇数杯。我们现在的工作流程是相同的,但情况正好相反 提起5号杯子:再次提起5号杯子。球不在那里。根据新的假设,球现在将移动到第2或第4杯(同样,它不能移动到第6杯,因为它不在5杯以下)Algorithm 在尽可能少的步骤中找到运动目标的算法,algorithm,search,optimization,Algorithm,Search,Optimization,我正试图解决以下问题: 一排有6个杯子(比如编号1到6)。其中一个杯子下面有一个球(我不知道是哪一个)。我可以举起一个杯子,看看球是否在那里。如果是,我赢了。如果不是,球将从其当前位置移动到一个杯上,直接向左或向右移动(因此从杯4移动到杯3或杯5。从杯6移动到杯5)。球必须移动,不能停留在原地 问题是:如果你使用最佳策略,经过多少次“杯托”后,你会知道球的位置 目前,我已经想出了一个策略,最坏的情况是6部电梯。请注意,不需要进行最后的举重,“证明”球的位置。我的问题是:是否有一种算法具有更好的“
提起6号杯子:提起4号杯子。它不在那里,所以它必须在2号杯子下面(它在一个均匀的杯子下面,而不是在6号或4号杯子下面)。因此,我们知道杯子在哪里(即使我们没有执行第2号杯子的最终提升)。您的算法有缺陷。如果球在奇数位置开始,经过偶数次移动后,它将在奇数位置结束。您的算法假设它在六次移动后处于平衡位置。那是行不通的。此外,你的举重顺序并不能确定球在哪里 例如,假设球从杯1下开始。按照您的电梯顺序,以下是可能的
希望有帮助。如果你想用一个程序解决这个问题,请构造一个图,其中顶点是球可能所在的位置集,边是杯托,结果不会露出球。然后,一个解决方案是从您想要的任何起始状态到具有2个可能的杯托的任何状态的最短路径。(在a结束的终止条件有点混乱,因为规则允许它在球移动之前“知道”球在哪里) 这段代码相当粗糙,但使用DFS来查找最短路径,然后漂亮地打印解决方案。它证实了在最坏的情况下,需要6次提杯才能找到球,事实上,找到的解决方案与你所做的完全相同 输出为:
$ python cups.py
the ball can be under cups: 1,2,3,4,5,6
lift cup 2
the ball can be under cups: 2,3,4,5,6
lift cup 3
the ball can be under cups: 1,3,4,5,6
lift cup 4
the ball can be under cups: 2,4,5,6
lift cup 5
the ball can be under cups: 1,3,5
lift cup 5
the ball can be under cups: 2,4
lift cup 2
代码是:
import collections
N = 6
MASK = (1<<N)-1
def bitcount(n):
if n == 0: return 0
return 1 + bitcount(n & (n-1))
def shifts(c):
return ((c << 1) | (c >> 1)) & MASK
def adjacent(c):
if bitcount(c) == 2:
yield min(i for i in xrange(N) if (c>>i)&1), 0
return
for i in xrange(N):
if (c>>i)&1:
yield i, shifts(c & ~(1<<i))
def bfs(edges, start):
prev = {start: None}
q = collections.deque([start])
while q:
x = q.popleft()
for y in edges[x]:
if y in prev: continue
prev[y] = x
q.append(y)
return prev
def path(x, prev):
if x is None: return []
return path(prev[x], prev) + [x]
edges = dict((v, [n for _, n in adjacent(v)]) for v in xrange(2**N))
best_path = path(0, bfs(edges, MASK))
for pi, p in enumerate(best_path[:-1]):
print 'the ball can be under cups: %s' % ','.join(str(i+1) for i in xrange(N) if (p>>i)&1)
print 'lift cup %d' % list(c+1 for c, n in adjacent(best_path[pi]) if n == best_path[pi+1])[0]
导入集合
N=6
掩码=(1>i)&1),0
返回
对于x范围内的i(N):
如果(c>>i)&1:
产量i,位移(c&~(1i)和1)
打印“提升杯%d%”列表(c+1代表c,n在相邻(最佳路径[pi]),如果n==最佳路径[pi+1])[0]
我们假设球在开始时在一个均匀的杯子下(所以是2、4或6)
为什么?作为限制搜索空间的初始方法:如果假设是正确的,那么我们只需要三次提起就可以找到它。这是找到一种最坏情况为6次提升的方法所需要的——如果你不需要假设我洗耳恭听的话;)这是一个非常奇怪的假设。似乎这无助于构建通用解决方案。很久以前,我在五个地方解决了类似的问题(猫/鼠标是更可靠的模型:)。假设2*n-4个镜头是最好的可能结果,您可以编写一些代码来运行所有组合,以找到最佳的提升顺序。只有6*2^6种可能的球的移动顺序和6^6种可能的6步6杯的举杯顺序——完成所有这些动作只需要几秒钟。如果你在寻找理论证据,你可能是在错误的位置。我的建议是要么要么要么(看起来更像数学而不是计算机科学,但我不确定这个问题是否会涉及到这两个方面的话题)。从我如何表述我的问题来看,可能还不够清楚,但在我举起杯子的那一刻,球还没有移动。所以你是对的,在第6步之后,球将移动到1或3。但是,在步骤6中,它必须位于杯2下(在最坏的情况下)。所以在这一点上,在它移动到第一杯之前,我知道它在第二杯下面(尽管我没有提起它)@radial:谢谢你的澄清。