蒙提霍尔三门问题

三门问题——亦称为蒙提霍尔问题,出自美国的电视游戏节目Let's Make a Deal。问题的名字来自该节目的主持人蒙提·霍尔(Monty Hall)。问题是这样的:
(15分)你的面前有一模-样的三扇门,你选定其中一扇门后就可以得到该门背后的东西。只有一- 扇门的背后有你梦寐以求的高级跑车,剩下两扇门的背后只有羊。有位主持人知道每扇门背后的详细情况。主持人先让你选择-一个门, 你选择后告诉了他,他再把另一个不是你选的门打开,告诉你里面是羊。现在只剩两扇门了,一扇是你刚开始选的,另一扇是主持人没有打开的。现在主持人问你:你是坚持你--开始的选择呢,还是换到另--扇剩下的门?请你通过编写随机模拟代码来确认你的结论。 (你可以使用任何语言的代码,或仅采用伪代码描述)
普通算法
思路一:逆向思考:
如果主持人问你换不换的时候,你坚决不换,你参加了1000次,主持人问了你1000次,你都说我不换。那好,主持人给你的提示对你没有影响,也就是说,主持人开剩下的两道门之一,对你没有任何影响。什么意思呢?就是你做的事情就是三选一,那你1000次参加,大概你能中奖333次。不换的结果就是中奖概率是三分之一。
所以你换的话,就是2/3的概率中奖。这是从反面来推测的。
思路二,直接法,等价推转换。我觉得这种理解最好。。
还是假设你参加了1000次这样的活动吧,我们把问题这样转换以下会变得非常有意思。你选了三张门中的一个,现在主持人问你:给你一次机会,你可以放弃你手里的一张门,而选我这边的两扇门(两扇门都归你,后面有可能有一车一羊,或两只羊),不过你得把你这两扇门后的一只羊给我,你换不换?
换,当然换,每次可以选两张门,这样概率是多大,当然是2/3了。
如何用计算机语言解决数学问题
大概懂了,那就是用高频尝试求概率
javascript解法
我感觉写了很长时间,事实证明如果我考试考到这题基本上就没办法了。。。当然还可以继续优化
//三门问题
function hostOpen(select,array){
//给出主持人打开的门的序号
var n = 0 //n是主持人打开的那扇门的序号
if(array[select]){
//如果选的就是跑车序号
while(n == select){
n = randomNum(0,2)
}
}else{
//如果选的不是跑车序号
while(n==select||array[n]==true){
n = randomNum(0,2)
}
}
return n
}
function changeOpen(host,select){
//给出更换后的我选择的门的序号
return 3-host-select
}
function isWin(select,array){
//是否胜利
if(array[select]){
return true
}else{
return false
}
}
function randomNum(minNum,maxNum){
//生成a和b之间的随机整数
switch(arguments.length){
case 1:
return parseInt(Math.random()*minNum+1,10);
break;
case 2:
return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10);
break;
default:
return 0;
break;
}
}
function main(){
var count = 1000
var changeWin = 0
var directWin = 0
var select = 0
var host = 0
var change = 0
for (var i = 0;i<count;i++){
var list = [false,false,false]
car = randomNum(0,2)
list[car]=true
select = randomNum(0,2)
host = hostOpen(select,list)
change = changeOpen(host,select)
// console.log("我选的是第"+(select+1)+"扇门")
// console.log("主持人打开了第"+(host+1)+"扇门")
// console.log("如果我不更换,那么我"+isWin(select,list))
// console.log("如果我更换,我会更换打开第"+(change+1)+"扇门,同时我"+isWin(change,list))
// console.log(list)
if(isWin(select,list)){
directWin ++
}else{
changeWin ++
}
}
console.log("一共尝试"+count+"次,不改变赢"+directWin+"次,胜率"+(directWin/10000)+" 改变赢"+changeWin+"次,胜率"+(changeWin/10000))
}
main()

python解法
这个用了python的random库,似乎简单不少,43行
from random import choice
def stay():
doors = ['car','goat','goat'] #设置三扇门,其中两扇门后面是山羊,一扇门后是汽车
choose = choice(doors) #随机选择一扇门
if choose == 'car': #不换门则直接判断
return 'win'
else:
return 'lose'
def switch():
doors = ['car', 'goat', 'goat']
choose = choice(doors)
doors.remove(choose) #选择的门放一边
doors.remove('goat') #剩下的门,去掉一只山羊
if doors == ['car']: #换门
return 'win'
else:
return 'lose'
if __name__ == '__main__':
total = 100000
count_switch = 0
win_switch = 0
count_stay = 0
win_stay = 0
for i in range(total):
choose = choice([1,2]) #随机选择换门还是不换门
if choose == 1:
count_switch += 1
if switch() == 'win':
win_switch += 1
else:
count_stay += 1
if stay() == 'win':
win_stay += 1
print('换门次数:',count_switch)
print('换门后得到汽车:',win_switch,'%.2f%%'%(100*win_switch/count_switch))
print('不换门:',count_stay)
print('不换门后得到汽车:',win_stay,'%.2f%%'%(100*win_stay/count_stay))
————————————————
版权声明:本文为CSDN博主「土豆洋芋山药蛋」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33414271/article/details/79321065
还有更短的
from random import*
x=randint(5000,10000) #随机设定一个试验次数
first_choice=0
change_choice=0
for i in range(1,x+1):
n=randint(1,3) #随机生成一个数代表藏有汽车的数
m=randint(1,3) #随机生成一个数代表参赛者的选择
if m==n: #参赛者没有改变选择
first_choice+=1
else: #参赛者改变了选择
change_choice+=1
print("不更改选择,猜中汽车的几率为:{:.4f},更改选择,猜中汽车的几率为:{:4f}".format(first_choice/x,change_choice/x))
