足球比赛具有一定程度的偶然性,弱队也有战胜强队的可能。
假设有甲、乙、丙、丁四个球队。根据他们过去比赛的成绩,得出每个队与另一个队对阵时取胜的概率表:
甲 乙 丙 丁
甲 - 0.1 0.3 0.5
乙 0.9 - 0.7 0.4
丙 0.7 0.3 - 0.2
丁 0.5 0.6 0.8 -
数据含义:甲对乙的取胜概率为0.1,丙对乙的胜率为0.3,...
现在要举行一次锦标赛。双方抽签,分两个组比,获胜的两个队再争夺冠军。(参见【1.jpg】)
请你进行10万次模拟,计算出甲队夺冠的概率。
p = 1 - 甲输的概率
甲输的话,有两种情况:
1:甲在第一轮中就输了
2:甲在晋级后,决赛中输了
假设 甲 先和 X 对决,则另两组是 Y 和 Z 对决
其中 Y 和 Z 对决有两种情况发生:要么Y赢,要么Z赢
所以综合上述讨论,可以算出甲输的概率是:
P(X, 甲) + P(甲,X)*P(Y, Z)*P(Y, 甲) + P(甲,X)*P(Z, Y)*P(Z, 甲)
即甲赢的概率是 1 减去上诉结果。
10万数据模拟可以得到甲赢的概率大约0.076。
验算:甲换成乙丙丁后分别算出四个数据,相加为1.0
#include <cstdio>
#include <stdlib.h>
#include <time.h>
#define COUNT 100000
const int g = 0;
double P[4][4] = {{0, 0.1, 0.3, 0.5},
{0.9, 0, 0.7, 0.4},
{0.7, 0.3, 0, 0.2},
{0.5, 0.6, 0.8, 0}
};
int main()
{
srand((unsigned)time(NULL));
double sum = 0.0;
for(int k = 1; k <= COUNT; k++)
{
int x = g, y = g, z = g;
while(x == g) x = rand() % 4;
//while(y==g || y==x) y=rand()%4; //此处的生成y的方法和下面的方法有轻微差异
for(int ii = 0; ii < 4 && (ii == g || ii == x); )++ii; //约有0.001的浮动,推荐用下面这个方法
y = ii;
for(int i = 0; i < 4 && (i == g || i == x || i == y); )++i;
z = i;
double r = 1 - (P[x][g] + P[g][x] * (P[y][z] * P[y][g] + P[z][y] * P[z][g]));
sum += r;
}
printf("%lf\n", sum / COUNT);
return 0;
}