离散课上一道问题:
参赛者会看见三扇关闭了的门,其中一扇的后面有一辆汽车,选中后面有车的那扇门可赢得该汽车,
另外两扇门后面则各藏有一只山羊。当参赛者选定了一扇门,但未去开启它的时候,节目主持人开
启剩下两扇门的其中一扇,露出其中一只山羊。主持人其后会问参赛者要不要换另一扇仍然关上的
门。问题是:换另一扇门会否增加参赛者赢得汽车的机会率?
#include<iostream>
#include<ctime>
using namespace std;
const int doors_num = 3;
static double choice_one = 0; //不换门的总中奖次数
static double choice_two = 0;// 换门的总中奖次数
const int times = 100000000;// 总过模拟次数
double get_probability(int times, bool status);
int random(int, int);
void set_status(bool []);
int main(){
srand(time(0));
int cho_one = 1; //不换门
int cho_two = 0; //换门
cout << get_probability(times, cho_one) << endl;
cout << get_probability(times, cho_two) << endl;
}
double get_probability(int times, bool status){
int t = times;
bool doors[doors_num];
while (t--){
set_status(doors);
int choice = random(0,2);
//不换门的情况 随机选中一个 如果门后是1 则中奖次数加一
if (status){
if (doors[choice] == 1){
choice_one++;
}
}
//换门后的情况 随机选择一个 x 号门 然后随机选择一个门后为 0 y号的门 最终如果 除去x,y 门的第三个门 后为1 则中奖次数加一
else{
int c;
// do 选出 门后为0 的门
do{
c = random(0,2);
} while (doors[c] || c == choice);
// 除去x,y 门的第三个门
int left_door = (doors_num - 1)*doors_num / 2 - choice - c;
if (doors[left_door]==1){
choice_two++;
}
}
}
if (status)
return (double)choice_one / times;
else
return (double)choice_two / times;
}
//该函数随机设置三个门后面的状态
void set_status(bool doors[]){
bool s;
//
//memset(doors, 0, sizeof(doors));原来的写法 sizeof(doors)=4 所以越界了
memset(doors, 0, doors_num);
int i = 0;
// 出现1则表示 当前第 i%3 号门 后面为车子
while (true)
{
s = random(0, 1);
if (s){
doors[i%doors_num] = 1;
break;
}
i++;
}
}
// 随机数生成
int random(int s, int f){
return rand() % (f -s+ 1 )+ s;
}
在 set_status 函数里面 使用的memset函数 出了点小问题
之前以为传进来的是整个对象,但其实只是对象首地址的指针,所以当sizeof(doors)得到的值是doors这个指针的大小,指针的大小都是32位,四个字节,于是就出现越界问题。