足球比赛具有一定程度的偶然性,弱队也有战胜强队的可能。
假设有甲、乙、丙、丁四个球队。根据他们过去比赛的成绩,得出每个队与另一个队对阵时取胜的概率表:
甲 乙 丙 丁
甲 - 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; }