Football(概率dp)
阿新 • • 發佈:2021-08-11
題目大意
有一場足球賽,一共有\(n\)輪,上一輪勝出的隊伍與這一輪與其相鄰的隊伍比賽(1和2,3和4) 給你任意兩個隊比賽會獲勝的概率,求最後那個隊獲勝的概率最大。
解題思路
第一輪兩個隊之間有一個會獲勝,第二輪四個隊之間有一個會獲勝,第三輪8個隊之間有一個會獲勝...第一輪分成人數為1的小組,第二輪分成人數為2的小組,第三輪分成人數為3的小組...發現每輪比賽都是第1組和第2組打,第3組和第4組打。
然後就是計算概率了,可以發現每輪每個隊的獲勝概率有遞推關係,設\(dp[i][j]\)表示第\(i\)隊第\(j\)輪勝出,那麼第\(i\)隊第\(j+1\)輪勝出的概率就是和相鄰組打所有勝出情況的概率之和。即\(dp[i][j+1] = \sum {dp[i][j]\times p[i][k]\times dp[k][j]}\)
const int maxn = 1e3+10; const int maxm = 1e6+10; double p[maxn][maxn], dp[maxn][maxn]; int main() { //IOS; int t; while(cin >> t && (~t)) { int n = 1<<t; for (int i = 0; i<n; ++i) for (int j = 0; j<n; ++j) scanf("%lf", &p[i][j]); for (int i = 0; i<n; ++i) dp[i][0] = 1; for (int i = 0; i<t; ++i) { int sz = 1<<i; //cout << "_____________i_______________" << endl; for (int j = 0; j<n; ++j) { //cout << "-----j-----" << endl; int now = j/sz; double sum = 0; if (now&1) { for (int k = (now-1)*sz; k<now*sz; ++k) { sum += dp[j][i]*p[j][k]*dp[k][i]; //cout << j << ' ' << k << endl; } } else { for (int k = (now+1)*sz; k<(now+2)*sz; ++k) { sum += dp[j][i]*p[j][k]*dp[k][i]; //cout << j << ' ' << k << endl; } } dp[j][i+1] = sum; //cout << sum << endl; } } int ans = 0; for (int i = 0; i<n; ++i) if (dp[ans][t]<dp[i][t]) ans = i; cout << ans+1 << endl; } return 0; }