今天,和同事们聊到个有趣的问题:"有3扇门,1,2,3,其中有扇门有辆汽车,如果选中正确的那扇门,就可以获得汽车.首先,你可以选择一扇门,然后,主持人可以在另外两扇门中排出一扇错误的门,这个时候,你可以选择坚持已经选择的门,或者换另外一扇门".
比如说:
1 2 3
我选择1
主持人排出了3
还剩余1 2
我可以继续坚持选1,或者放弃,而改选2
起初,我认为的中奖概率为:
1 2 3
1/3 1/3 1/3
当主持人排出3后,中奖概率为:
1 2 3
1/2 1/2 0
但实际上这是错误的理解!我通过程序测试了上万次,正确的概率为:
1 2 3
1/3 2/3 0
代码如下
package openthedoor;
import java.util.Random;
import java.util.Scanner;
/**
*
* @author Vicky.H
* @email eclipser@163.com
*/
public class OpenTheDoor {
// 记录猜对的次数
private static int win = 0;
// 记录玩家选择的门
private static int enter = 0;
private static Random random = new Random();
private static boolean doors[] = new boolean[3];
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("程序说明:\n输入1,2,3之间的数字代表一个门,每次将随机排列门中是否有宝马!\n共猜1000次,如果第一次就猜中,将不计算在10次内!");
run(1);
System.err.println("死脑筋,坚持1不变:1000次猜对:" + win + ",概率为:" + win / 1000.0);
System.out.println("------------------------");
win = 0;
run2(1);
System.err.println("开始选1,系统筛选后,选择另外一个数:1000次猜对:" + win + ",概率为:" + win / 1000.0);
}
/**
* 坚持选择一个数
* @param enter
*/
private static void run(int enter) {
for (int i = 0; i < 1000; i++) {
initDoors();
System.out.println(">>>第" + i + "次测试开始:");
doors[random.nextInt(3)] = true;
try {
// enter = new Scanner(System.in).nextInt();
if (enter < 1 || enter > 3) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
} catch (Exception e) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
int falseDoor = getFalseDoor(enter - 1); // 这条语句已经将概率做了改变!!!!!!!!!!
System.out.println("系统排出一个错误的门:" + falseDoor + " !请输入另外一个不为:" + falseDoor + "门");
try {
// enter = new Scanner(System.in).nextInt();
if (enter < 1 || enter > 3 || enter == falseDoor) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
} catch (Exception e) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
if (doors[enter - 1]) { // 第二次输入
win++;
System.out.println("第二次猜中,共猜对:" + win + "次!!!");
} else {
System.out.println("第二次未能猜对!");
}
System.out.println(doors[0] + " ," + doors[1] + " ," + doors[2]);
}
}
/**
* 选择另外个数
* @param enter
*/
private static void run2(int enter) {
for (int i = 0; i < 1000; i++) {
initDoors();
System.out.println(">>>第" + i + "次测试开始:");
doors[random.nextInt(3)] = true;
try {
// enter = new Scanner(System.in).nextInt();
if (enter < 1 || enter > 3) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
} catch (Exception e) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
int falseDoor = getFalseDoor(enter - 1); // 这条语句已经将概率做了改变!!!!!!!!!!
System.out.println("系统排出一个错误的门:" + falseDoor + " !请输入另外一个不为:" + falseDoor + "门");
// 选择另外一个数
int tmp = random.nextInt(3) + 1;
while(enter == tmp || enter == falseDoor){
tmp = random.nextInt(3) + 1;
}
enter = tmp;
try {
// enter = new Scanner(System.in).nextInt();
if (enter < 1 || enter > 3 || enter == falseDoor) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
} catch (Exception e) {
System.out.println("请输入1,2,3之中的数字!");
i--;
continue;
}
if (doors[enter - 1]) { // 第二次输入
win++;
System.out.println("第二次猜中,共猜对:" + win + "次!!!");
} else {
System.out.println("第二次未能猜对!");
}
System.out.println(doors[0] + " ," + doors[1] + " ," + doors[2]);
}
}
private static void initDoors() {
doors[0] = false;
doors[1] = false;
doors[2] = false;
}
private static int getFalseDoor(int enter) {
int i = random.nextInt(3);
while (i == enter) {
i = random.nextInt(3);
}
if (!doors[i]) {
return i + 1;
} else {
return getFalseDoor(enter);
}
}
}
死脑筋,坚持1不变:1000次猜对:362,概率为:0.362
开始选1,系统筛选后,选择另外一个数:1000次猜对:655,概率为:0.655
死脑筋,坚持1不变:1000次猜对:341,概率为:0.341
开始选1,系统筛选后,选择另外一个数:1000次猜对:656,概率为:0.656