CodeForces - 859D Third Month Insanity dfs + 概率期望

傳送門:Codeforces 859D

題意:有 2^n 個隊伍進行比賽,每次都是編號相鄰的的兩隊伍比賽,勝出的晉級下一輪,失敗的淘汰,這樣n輪過後只剩一隻隊伍時停止。每一場比賽你都可以賭某個隊伍贏,第一輪賭中了獲得一分,後面每輪賭中得分翻倍,現在給出每兩個隊伍比賽的勝負概率,問你最大得分期望是多少。


整個比賽過程其實就是一顆完全二叉樹,每一輪比賽對應二叉樹的一層,每一場比賽對應二叉樹的一個節點,

設 w[i][j] := 第i場比賽j隊伍贏的概率,e[i][j] := 第i場比賽猜j隊伍贏的總得分期望 

i按照二叉樹的結點編號來算

然後dfs過程中維護這兩個數組就行了。

代碼:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
const int MAXN = 100010;
double p[100][100];
double w[500][100];// w[i][j] := 第i場比賽j隊伍贏的概率 
double e[500][100];//e[i][j] := 猜第i場比賽j隊伍贏的得分期望 
void dfs(int score, int l, int r, int rt)
{
	if(l == r)
	{
		w[rt][l] = 1;
		e[rt][l] = score;
		return ; 
	}
	int mid = (l + r) >> 1;
	dfs(score / 2, l, mid, lson);
	dfs(score / 2, mid + 1, r, rson);
	for(int i = l; i <= mid; i++)
	for(int j = mid + 1; j <= r; j++)
	w[rt][i] += w[lson][i] * w[rson][j] * p[i][j];
	for(int i = mid + 1; i <= r; i++)
	for(int j = l; j <= mid; j++)
	w[rt][i] += w[rson][i] * w[lson][j] * p[i][j];
	for(int i = l; i <= mid; i++)
	for(int j = mid + 1; j <= r; j++)
	e[rt][i] = max(e[rt][i], w[rt][i] * score + e[lson][i] + e[rson][j]);
	for(int i = mid + 1; i <= r; i++)
	for(int j = l; j <= mid; j++)
	e[rt][i] = max(e[rt][i], w[rt][i] * score + e[rson][i] + e[lson][j]);
}
int main()
{
	int n, t;
	cin >> n;
	n = 1 << n;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		scanf("%d", &t), p[i][j] = 0.01 * t;
	}
	dfs(n / 2, 1, n, 1);
	printf("%.10lf", *max_element(e[1], e[1] + n + 1));
 	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章