1 条题解
-
0
方法思路
- 理解赛制结构:比赛是单淘汰赛,共有16个国家,分成四轮(16进8,8进4,4进2,决赛)。我们需要按照这个结构逐步计算每个国家在每一轮晋级的概率。
- 动态概率计算:对于每一轮,每个国家晋级的概率等于它在当前轮次击败所有可能对手的概率乘以对手晋级到当前轮次的概率之和。具体来说:
- 第一轮(16进8):国家i的对手是固定的(根据赛程结构),计算国家i击败对手的概率,直接得到进入下一轮的概率。
- 后续轮次:国家i在下一轮的对手是前一轮两个胜者之一,因此需要计算国家i击败这两个潜在对手的概率,并乘以这两个对手各自晋级到当前轮次的概率,然后将结果相加。
- 递归或迭代处理:可以使用动态规划的方法,维护一个二维数组
dp[k][i]
,表示国家i在第k轮(0到3轮,0表示第一轮)晋级的概率。初始化时,dp[0][i]
是国家i在第一轮击败直接对手的概率。然后,对于每一轮k,计算国家i击败所有可能对手的概率乘以对手在上一轮晋级的概率之和。
解决代码
#include <iostream> #include <vector> #include <string> #include <iomanip> #include <cstdio> using namespace std; struct Country { string name; vector<double> win_prob; // win_prob[j] is probability that this country beats country j (0-based) }; int main() { vector<Country> countries(16); for (int i = 0; i < 16; ++i) { cin >> countries[i].name; } for (int i = 0; i < 16; ++i) { countries[i].win_prob.resize(16); for (int j = 0; j < 16; ++j) { int p; cin >> p; countries[i].win_prob[j] = p / 100.0; } } vector<vector<double> > dp(4, vector<double>(16, 0.0)); // Initialize round 0 probabilities // Match 1: 0 vs 1 dp[0][0] = countries[0].win_prob[1]; dp[0][1] = countries[1].win_prob[0]; // Match 2: 2 vs 3 dp[0][2] = countries[2].win_prob[3]; dp[0][3] = countries[3].win_prob[2]; // Match 3: 4 vs 5 dp[0][4] = countries[4].win_prob[5]; dp[0][5] = countries[5].win_prob[4]; // Match 4: 6 vs 7 dp[0][6] = countries[6].win_prob[7]; dp[0][7] = countries[7].win_prob[6]; // Match 5: 8 vs 9 dp[0][8] = countries[8].win_prob[9]; dp[0][9] = countries[9].win_prob[8]; // Match 6: 10 vs 11 dp[0][10] = countries[10].win_prob[11]; dp[0][11] = countries[11].win_prob[10]; // Match 7: 12 vs 13 dp[0][12] = countries[12].win_prob[13]; dp[0][13] = countries[13].win_prob[12]; // Match 8: 14 vs 15 dp[0][14] = countries[14].win_prob[15]; dp[0][15] = countries[15].win_prob[14]; // Compute probabilities for subsequent rounds for (int r = 1; r < 4; ++r) { for (int i = 0; i < 16; ++i) { double prob = 0.0; if (r == 1) { // Quarterfinals if (i == 0 || i == 1 || i == 2 || i == 3) { // QF1 int possible_opponents[2]; if (i == 0 || i == 1) { possible_opponents[0] = 2; possible_opponents[1] = 3; } else { possible_opponents[0] = 0; possible_opponents[1] = 1; } for (int k = 0; k < 2; ++k) { int j = possible_opponents[k]; prob += dp[r-1][j] * countries[i].win_prob[j]; } prob *= dp[r-1][i]; } else if (i == 4 || i == 5 || i == 6 || i == 7) { // QF2 int possible_opponents[2]; if (i == 4 || i == 5) { possible_opponents[0] = 6; possible_opponents[1] = 7; } else { possible_opponents[0] = 4; possible_opponents[1] = 5; } for (int k = 0; k < 2; ++k) { int j = possible_opponents[k]; prob += dp[r-1][j] * countries[i].win_prob[j]; } prob *= dp[r-1][i]; } else if (i == 8 || i == 9 || i == 10 || i == 11) { // QF3 int possible_opponents[2]; if (i == 8 || i == 9) { possible_opponents[0] = 10; possible_opponents[1] = 11; } else { possible_opponents[0] = 8; possible_opponents[1] = 9; } for (int k = 0; k < 2; ++k) { int j = possible_opponents[k]; prob += dp[r-1][j] * countries[i].win_prob[j]; } prob *= dp[r-1][i]; } else if (i == 12 || i == 13 || i == 14 || i == 15) { // QF4 int possible_opponents[2]; if (i == 12 || i == 13) { possible_opponents[0] = 14; possible_opponents[1] = 15; } else { possible_opponents[0] = 12; possible_opponents[1] = 13; } for (int k = 0; k < 2; ++k) { int j = possible_opponents[k]; prob += dp[r-1][j] * countries[i].win_prob[j]; } prob *= dp[r-1][i]; } } else if (r == 2) { // Semifinals if (i >= 0 && i <= 7) { // SF1 int possible_opponents[4]; if (i >=0 && i <=3) { possible_opponents[0] = 4; possible_opponents[1] = 5; possible_opponents[2] = 6; possible_opponents[3] = 7; } else { possible_opponents[0] = 0; possible_opponents[1] = 1; possible_opponents[2] = 2; possible_opponents[3] = 3; } for (int k = 0; k < 4; ++k) { int j = possible_opponents[k]; prob += dp[r-1][j] * countries[i].win_prob[j]; } prob *= dp[r-1][i]; } else { // SF2 int possible_opponents[4]; if (i >=8 && i <=11) { possible_opponents[0] = 12; possible_opponents[1] = 13; possible_opponents[2] = 14; possible_opponents[3] = 15; } else { possible_opponents[0] = 8; possible_opponents[1] = 9; possible_opponents[2] = 10; possible_opponents[3] = 11; } for (int k = 0; k < 4; ++k) { int j = possible_opponents[k]; prob += dp[r-1][j] * countries[i].win_prob[j]; } prob *= dp[r-1][i]; } } else if (r == 3) { // Final if (i >=0 && i <=7) { // Opponents from SF2 (8..15) for (int j = 8; j <16; ++j) { prob += dp[r-1][j] * countries[i].win_prob[j]; } } else { // Opponents from SF1 (0..7) for (int j =0; j <8; ++j) { prob += dp[r-1][j] * countries[i].win_prob[j]; } } prob *= dp[r-1][i]; } dp[r][i] = prob; } } for (int i = 0; i < 16; ++i) { cout << left << setw(10) << countries[i].name << " p=" << fixed << setprecision(2) << dp[3][i]*100 << "%" << endl; } return 0; }
- 1
信息
- ID
- 1262
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者