POJ3071 Football

题目传送门


思路

状态设计

考虑到让求在第 \(n\) 轮比赛(决赛)中获胜概率最大的球队。因此,我们需要知道每一轮中,每个队伍的获胜概率。\(\\\)
因此设 \(dp_{i, j}\) 为在第 \(i\) 轮时,\(j\) 获胜的概率。\(\\\)

转移方程

由于我们要知道球队 \(j\) 在第 \(i\) 轮比赛中的胜率,所以就要算出它与所有【在上一轮比赛中可能获胜的球队 \(k\)】对战的胜率之和,即就是:

\[dp_{i, j} = \sum_{k \in \left\{x|可能与 j 对战的球队 \right\}} dp_{i - 1, j} \times dp_{i - 1, k} \times p_{j, k} \]

当然还要考虑有哪些 \(k\) 可能与 \(j\) 对战:\(\\\)

  1. 对于第 \(i\) 轮比赛,它一共包含(所有比赛还未开始时的)\(2^i\) 支球队,因此我们可以将这 \(2^n\) 个球队以每 \(2^i\) 个为一组分成若干块。\(\\\)
    对于要对战的球队 \(j, k\),我们首先要看他们是否在同一个块中,即看:
    \(\frac{j + 2^i - 1}{2^i} = \frac{k + 2^i - 1}{2^i}\)是否成立。
  2. 假如我们现在判断出了 \(j, k\) 已经在这样一个 \(2^i\) 的大块中了,那么我们将这个大块均分成两个大小为 \(2^{i - 1}\) 的小块(即模拟上一轮比赛中可能包含的队伍),我们就要更近一步判断 \(j, k\) 是否分属于两个不同的小块,这样才合法(因为若在同一个小块中,由于前提是 \(j\) 已经进入了第 \(i\) 轮,所以这个小块中的其他球队不可能再与之对战)。因此,要看 \(\frac{j + 2^{i - 1} - 1}{2^{i - 1}} \neq \frac{k + 2^{i - 1} - 1}{2^{i - 1}}\) 是否成立。

边界条件

在进行第 \(0\) 轮比赛(即还没有开始比赛)时,每个球队一定晋级,即:\(dp_{0, j} = 1, j \in [1, n]\)

答案

就是 \(max \left\{dp_{n, i} \right\}\)\(i\)

复杂度

空间 \(O(n \times 2^n)\),时间 \(O(n^2 \times 2^n)\)


代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = (1 << 7) + 7;

int n, m;
double p[maxn][maxn];
double dp[15][maxn];
int main() {
	scanf("%d", &m), n = 1 << m;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			scanf("%lf", &p[i][j]);
	int x; scanf("%d", &x);
	for (int i = 1; i <= n; ++i) dp[0][i] = 1;
	for (int i = 1; i <= m; ++i) {
		for (int j = 1; j <= n; ++j) {
			for (int k = 1; k <= n; ++k) {
				if (j == k) continue;
				if ((j + (1 << i) - 1) / (1 << i) != (k + (1 << i) - 1) / (1 << i)) continue;
				if (abs((j + (1 << i - 1) - 1) / (1 << i - 1) - 
						(k + (1 << i - 1) - 1) / (1 << i - 1)) != 1) continue;
				dp[i][j] += dp[i - 1][j] * dp[i - 1][k] * p[j][k];
			}
		}
	}
	double maxp = 0;
	int id = 0;
	for (int i = 1; i <= n; ++i)
		if (maxp < dp[m][i])
			maxp = dp[m][i], id = i;
	printf("%d\n", id);
	return 0;
} 
posted @ 2025-04-06 10:56  syzyc  阅读(36)  评论(0)    收藏  举报