美團codeM資格賽——世界盃

一、題目描述

世界盃就要開始啦!真真正正的戰鬥從淘汰賽開始,現在我們給出球隊之間的勝負概率,來預測每支球隊奪冠的可能性。
在接下來的篇幅中,我們將簡單介紹淘汰賽階段的規則。
淘汰賽階段的90分鐘常規時間內(含補時階段)進球多的球隊取勝,如果參賽雙方在90分鐘內(含補時階段)無法決出勝負,將進行上下半場各15分鐘的加時賽。加時賽階段,如果兩隊仍未分出勝負,則通過點球大戰決出勝者。也就是說,每場比賽,有且僅有一個隊能夠晉級到下一輪。
淘汰賽共有16支球隊參加(小組賽階段共分8個小組,每組前兩名晉級),對陣安排如下。
1/8決賽
A組第一對陣B組第二=勝者1
B組第一對陣A組第二=勝者2
C組第一對陣D組第二=勝者3
D組第一對陣C組第二=勝者4
E組第一對陣F組第二=勝者5
F組第一對陣E組第二=勝者6
G組第一對陣H組第二=勝者7
H組第一對陣G組第二=勝者8
獲勝的8個隊進入1/4決賽,即所謂“8強”
1/4決賽
勝者1對陣勝者3=勝者A
勝者2對陣勝者4=勝者B
勝者5對陣勝者7=勝者C
勝者6對陣勝者8=勝者D
1/4決賽的4個獲勝隊進入“4強”
半決賽
勝者A對陣勝者C
勝者B對陣勝者D
半決賽獲勝兩隊進入決賽,失利的兩隊爭奪三名
決賽獲勝的隊伍就是最後的冠軍!
輸入描述:
球隊會被以1..16進行標號,其分別表示:
1 A組第一;
2 B組第二;
3 C組第一;
4 D組第二;
5 E組第一;
6 F組第二;
7 G組第一;
8 H組第二;
9 B組第一;
10 A組第二;
11 D組第一;
12 C組第二;
13 F組第一;
14 E組第二;
15 H組第一;
16 G組第二。

數據共有16行,每行16個浮點數,第i行第j列的數Fi,j表示i和j進行比賽時i獲勝(包括常規時間獲勝、加時賽獲勝以及點球大戰獲勝)的概率。
對於1 <= i, j <= 16 且 i != j, 滿足0 <= Fi,j <= 1, Fi,j + Fj,i = 1;
對於1 <= i <= 16, 滿足 Fi,i = 0。

輸出描述:
輸出一行16個浮點數,用空格隔開,分別表示每隻球隊獲得世界盃的概率,結尾無空格。
絕對誤差或相對誤差在1e-5之內的解會被判爲正確。
示例1

輸入

0.000 0.133 0.210 0.292 0.670 0.270 0.953 0.353 0.328 0.128 0.873 0.082 0.771 0.300 0.405 0.455
0.867 0.000 0.621 0.384 0.934 0.847 0.328 0.488 0.785 0.308 0.158 0.774 0.923 0.261 0.872 0.924
0.790 0.379 0.000 0.335 0.389 0.856 0.344 0.998 0.747 0.895 0.967 0.383 0.576 0.943 0.836 0.537
0.708 0.616 0.665 0.000 0.146 0.362 0.757 0.942 0.596 0.903 0.381 0.281 0.294 0.788 0.804 0.655
0.330 0.066 0.611 0.854 0.000 0.687 0.983 0.217 0.565 0.293 0.256 0.938 0.851 0.487 0.190 0.680
0.730 0.153 0.144 0.638 0.313 0.000 0.832 0.526 0.429 0.707 0.414 0.617 0.925 0.638 0.526 0.545
0.047 0.672 0.656 0.243 0.017 0.168 0.000 0.357 0.125 0.307 0.879 0.551 0.641 0.959 0.981 0.465
0.647 0.512 0.002 0.058 0.783 0.474 0.643 0.000 0.325 0.494 0.893 0.064 0.563 0.429 0.501 0.872
0.672 0.215 0.253 0.404 0.435 0.571 0.875 0.675 0.000 0.940 0.053 0.329 0.232 0.280 0.359 0.474
0.872 0.692 0.105 0.097 0.707 0.293 0.693 0.506 0.060 0.000 0.040 0.776 0.589 0.704 0.018 0.968
0.127 0.842 0.033 0.619 0.744 0.586 0.121 0.107 0.947 0.960 0.000 0.486 0.266 0.662 0.374 0.698
0.918 0.226 0.617 0.719 0.062 0.383 0.449 0.936 0.671 0.224 0.514 0.000 0.821 0.027 0.415 0.227
0.229 0.077 0.424 0.706 0.149 0.075 0.359 0.437 0.768 0.411 0.734 0.179 0.000 0.841 0.409 0.158
0.700 0.739 0.057 0.212 0.513 0.362 0.041 0.571 0.720 0.296 0.338 0.973 0.159 0.000 0.935 0.765
0.595 0.128 0.164 0.196 0.810 0.474 0.019 0.499 0.641 0.982 0.626 0.585 0.591 0.065 0.000 0.761
0.545 0.076 0.463 0.345 0.320 0.455 0.535 0.128 0.526 0.032 0.302 0.773 0.842 0.235 0.239 0.000

輸出

0.0080193239 0.1871963989 0.0797523190 0.1233859685 0.0836167329 0.0438390981 0.0079035829 0.0604644891 0.0237087902 0.0050549016 0.1149551151 0.0679247259 0.0511307364 0.0395744604 0.0800843771 0.0233889799

二、解決思路!

由題意可知
image
那麼 如果需要將十六支隊伍奪冠的概率計算出來,我們必須將十六支隊伍分別進入1/8決賽,1/4決賽,半決賽的概率都計算出來。給十六支隊伍加上編號,從1~16編號。創建數組D[4][16]分別表示每一支隊伍進入1/8決賽的概率,1/8決賽,1/4決賽,半決賽,獲得冠軍的概率
例:
我們看第一組獲得冠軍的概率
D[0][0] = F[0][1];也就是說假設第一支隊伍要進1/8決賽必須踢贏第二支隊伍
D[1][0] = ( D[0][2] * F[0][2] + D[0][3] * F[0][3] ) * D[0][0] ;也就是說假設第一隻隊伍要進1/4決賽必須要踢贏另外一組1/8決賽可能出現的所有隊伍的概率乘上自己進1/8決賽的概率
D[2][0] = ( D[1][4] * F[0][4] + D[1][5] * F[0][5] + D[1][6] * F[0][6] + D[1][7] * F[0][7] ) * D[1][0] ;也就是說假設第一隻隊伍要進半決賽必須要踢贏另外一組1/4決賽可能出現的所有隊伍的概率乘上自己進1/4決賽的概率
D[3][0] = ( D[2][8] * F[0][8] + D[2][9] * F[0][9] + D[2][10] * F[0][10] + D[2][11] * F[0][11] + D[2][12] * F[0][12] +D [2][13] * F[0][13] + D[2][14] * F[0][14] + D[2][15] * F[0][15] ) * D[2][0] ;也就是說假設第一隻隊伍要奪得冠軍必須要踢贏另外一組半決賽可能出現的所有隊伍的概率乘上自己進半決賽的概率
這樣求出了第一隻隊伍奪冠的概率
這時就會發現當算這一層的時候需要上一層作爲參考數據來計算,所以我們每一次將一層算完再計算下一層,這樣會減少很多不必要的計算

三、程序代碼

#include<stdio.h>
#include<string.h>
#include<math.h>
double F[16][16],D[4][16];
int main(){
    int i,j,k;
    for(i = 0;i < 16;i++){
        for(j = 0;j < 16;j++){
            scanf("%lf",&F[i][j]);
        }
    }
    memset(D,0,sizeof(D));
    for(i = 0;i < 16;i++){
        if(i%2)
            D[0][i] = F[i][i-1];
        else
            D[0][i] = F[i][i+1];
    }
    for(i = 1;i < 4;i++){
        for(j = 0;j < 16;j++){
            int l = (j+pow(2,i))/pow(2,i);
            if(l%2){
                for(k = l*pow(2,i);k < (l+1)*pow(2,i);k++){
                    D[i][j] += D[i-1][k]*F[j][k]*D[i-1][j];
                }  
            }else{
                for(k = (l-2)*pow(2,i);k < (l-1)*pow(2,i);k++){
                    D[i][j] += D[i-1][k]*F[j][k]*D[i-1][j];
                }  
            }
        }
    }
    for(i = 0;i < 15;i++){
        printf("%.10lf ",D[3][i]);
    }
    printf("%.10lf",D[3][i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章