poj 3071 概率dp

一个足球比赛有2^n个队伍参加。比赛按照队伍编号进行。1和2比、3和4比、5和6比...比完后1,2的胜利队伍和3,4的胜利队伍比...以此类推,知道最后只剩下一只队伍成为胜利者。


现在给出 n 和一个二维数组P,P[i][j] 表示编号 i 的队伍战胜编号为 j 的队伍的概率。
求最有可能成为获胜者的队伍编号。
观察题目我们可以发现比赛赛程是棵二叉树。所以我们可以利用树的结构解题。树的每个节点都表述队伍编号的一段区间我们要求的是该区间的每个队伍一路获胜并且到达该节点的

概率。
dp[t][i] : 表示t节点上编号为 i 的队伍获胜的概率。则 i号队伍必须在其所在的子树区间获胜,并打败另一个字树区间的获胜队伍。
dp[t][i] = dp[t1][i] * Σ(dp[t2][j] * p[i][j]);

但是明显这样表示的转移方程比较麻烦。我提供另一种思路。如果i号队伍在左子树区间获胜,j号队伍在右子树区间获胜,i战胜j则i在当前节点获胜。反之同理。
dp[t][i] += dp[t_l][i] * dp[t_r][j] * p[i][j];
dp[t][j] += dp[t_l][i] * dp[t_r][j] * p[j][i];

写代码的时候可以套用线段树的结构。


/***********************************************
 ** problem ID	: poj_3071.cpp
 ** create time	: Mon Jul 27 21:18:44 2015
 ** auther name	: xuelanghu
 ** auther blog	: blog.csdn.net/xuelanghu407
 **********************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

// dp[t][i] += p[i][j] * dp[tl][i] * dp[tr][j];
// dp[t][j] += p[j][i] * dp[tl][i] * dp[tr][j];
int n;
double p[(1<<7)+5][(1<<7)+5];

struct Node {
	double p[(1<<7) + 5];
}dp[(1<<10)];

void DP(int l, int r, int lr) {// cout<< lr << endl;getchar();
	
	if (l == r) {
		dp[lr].p[l] = 1.0;
		return ;
	}
	
	int mid = (l + r) >> 1; 
	DP(l, mid, lr<<1);
	DP(mid+1, r, lr<<1|1);
	
	for (int i=l; i<=mid; i++) {
		for (int j=mid+1; j<=r; j++) {
			dp[lr].p[i] += p[i][j] * dp[lr<<1].p[i] * dp[lr<<1|1].p[j];
			dp[lr].p[j] += p[j][i] * dp[lr<<1].p[i] * dp[lr<<1|1].p[j];
		}
	}
}

int main () {
	while (cin >> n) {
		if (n == -1) break;
		memset(dp, 0, sizeof(dp));
		
		for (int i=1; i<=(1<<n); i++) {
			for (int j=1; j<=(1<<n); j++) {
				cin >> p[i][j];
			}
		}
		DP(1, 1<<n, 1);
		
		double ans = 0.0;
		int pos = 0;
		for (int i=1; i<=(1<<n); i++) {
			if (ans < dp[1].p[i]) {
				ans = dp[1].p[i];
				pos = i;
			}
		}
		cout << pos << endl;
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值