1 条题解

  • 0
    @ 2025-5-6 21:19:40

    方法思路

    1. 理解赛制结构:比赛是单淘汰赛,共有16个国家,分成四轮(16进8,8进4,4进2,决赛)。我们需要按照这个结构逐步计算每个国家在每一轮晋级的概率。
    2. 动态概率计算:对于每一轮,每个国家晋级的概率等于它在当前轮次击败所有可能对手的概率乘以对手晋级到当前轮次的概率之和。具体来说:
      • 第一轮(16进8):国家i的对手是固定的(根据赛程结构),计算国家i击败对手的概率,直接得到进入下一轮的概率。
      • 后续轮次:国家i在下一轮的对手是前一轮两个胜者之一,因此需要计算国家i击败这两个潜在对手的概率,并乘以这两个对手各自晋级到当前轮次的概率,然后将结果相加。
    3. 递归或迭代处理:可以使用动态规划的方法,维护一个二维数组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
    上传者