题目:10个房间排成一条直线,只有一个房间有宝藏。每天宝藏都会移动到某个相邻房间。每天只能检查一个房间,请给出找到宝藏的ddl。
同类问题:十三间密室排成一排,小偷躲在其中一间,每过一天必转移到相邻的密室,转移方向随机。每天只能搜一间,问如何保证找到密室里的小偷?
1.可行解:
https://www.zhihu.com/question/20334205/answer/19711931
从1号房间逐个右移至n号房间,随后在n号房间停留一轮,然后从n号房间逐个左移至1号房间。
点评:可以保证任何情况下均可找到宝藏,但不是最优解,总共需要2n步。
2.最优解
https://www.zhihu.com/question/20334205/answer/14797333
https://www.zhihu.com/question/20334205/answer/17857467
从2号房间逐个右移至n-1号房间,随后在n-1号房间停留一轮,然后从n-1号房间逐个左移至2号房间。
点评:可以保证任何情况下均可找到宝藏,总共需要2(n-2)步。
3.部分可行解
https://www.zhihu.com/question/20334205/answer/17859185
https://mp.weixin.qq.com/s/uVw6H0FPn0ZjdFTcYtmpdA
从2号房间逐个右移至n-1号房间,随后再回到2号房间重复上一步,继续逐个右移至n-1号房间。
点评:无法保证在n为偶数且第一天搜查房间号和宝藏所藏的房间号差值为奇数的情况下一定能找到宝藏。
4.错误解
https://blog.csdn.net/zgottingen/article/details/8071925
房间数n为奇数时,先从1号房间逐个右移至n号房间,随后回到2号房间右移至n-1号房间。房间数n为偶数时,先从1号房间逐个右移至n-1号房间,随后回到2号房间右移至n号房间。
点评:无论房间数n为奇数还是偶数都无法保证一定能找到宝藏。
自己想的一个解法:
从2号房间逐个右移至n-1号房间,随后在n-1号房间停留一轮,随后回到2号房间继续右移至n-1号房间。
点评:无论房间数n为奇数还是偶数都无法保证一定能找到宝藏。
别人已经在数学上严格推导证明了答案的正确性,即只要我们按照最优策略去选择房间,那么一定能在最多2(n-2)天找到宝藏。但是并没有说最优策略下找到宝藏的天数的均值是多少。本博主又懒得去数学证明均值是多少,因此接下来本博主实现最优解的python代码,从大数据统计上来证明,根据大数定律,实验次数足够多的时候,最后找到宝藏的一定会趋近预期值。
import random
import sys
import numpy as np
plt.figure(figsize=(12,10))
n_array=[8,13,16,20]
for p in range(1, 5):
n=n_array[p-1]
day_find = []
day_find_aver = []
import matplotlib.pyplot as plt
#print("总共房间数:",n)
for i in range(1000):
room_treasure = random.randint(1, n)
#print("随机选择一间房作为宝藏第一天存放的房间:", room_treasure)
#print("开始执行最佳寻找策略:")
room_find = 2
day = 1
tag = 1 #遍历标签
while(room_find != room_treasure):
# 执行宝藏寻找策略
if(tag == 1 and room_find < n - 1):
room_find = room_find + 1
elif(tag == 2 and room_find <= n - 1):
room_find = room_find - 1
elif (tag == 1 and room_find == n - 1):
tag = 2
room_find = n - 1 #在n-1号房间停留一次
else:
print("出错了!room_find过大")
sys.exit()
# 宝藏随机移动到相邻房间
if(room_treasure > 1 and room_treasure < n):
room_treasure = room_treasure + random.choice([-1,1])
elif(room_treasure == 1 ):
room_treasure = room_treasure + 1
elif(room_treasure == n ):
room_treasure = room_treasure - 1
else:
print("出错了!room_treasure溢出")
sys.exit()
day = day + 1
if(day > 2*(n-2)):
print("出错了!day过大")
sys.exit()
#print("第",day,"天,找到了宝藏")
day_find = np.append(day_find, day)
day_find_aver = np.append(day_find_aver, day_find.mean())
plt.subplot(2, 2, p)
plt.plot(day_find, label='days to find treasure')
plt.plot(day_find_aver, label='average of days to find treasure')
plt.title('n='+ str(n) )
# 添加平均值线
plt.axhline(y=day_find_aver[-1], color='b', linestyle='--')
plt.text(x=0, y=day_find_aver[-1], s=f'{day_find_aver[-1]:.4f}')
# 添加最大值线
plt.axhline(y=day_find.max(), color='b', linestyle='--')
plt.text(x=0, y=day_find.max(), s=f'{day_find.max():.2f}')
plt.legend(loc='upper right')
plt.show()
结论:统计均值是一个小数,很好理解,因为寻找宝藏跟房间数的奇偶以及 第一天搜查房间号和宝藏所藏的房间号差值的奇偶有关。但是作者本人仅仅分辨上述几个网上找到可行又不可行的策略就筋疲力尽了,因此留待其他感兴趣的读者进一步研究这一最优解的期望值是多少。