您的位置:首页 > 其它

POJ 3071 Football [概率DP]

2015-12-08 16:33 309 查看
Description

Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, …, 2n. In each round of the tournament, all teams still in the tournament are placed in a list in order of increasing index. Then,
the first team in the list plays the second team, the third team plays the fourth team, etc. The winners of these matches advance to the next round, and the losers are eliminated. After n rounds, only one team remains undefeated; this team is declared
the winner.

Given a matrix P = [pij] such that pij is the probability that team i will beat team j in a match determine which team is most likely to win the tournament.

题意:

给出1<<n只队伍,他们两两之间开始比赛,赢的作为新的1<<(n-1)只队伍,继续两两比赛,其中队伍I打败队伍J的概率为Pij,问最后赢的概率最大的队伍是那一支(从1编号到1<<N)

范围:

N<=7

解法:

首先分析做法,发现其结构是一棵满二叉树,受到线段树维护信息的启发,可以考虑每一轮结束后,I队继续比赛下去的概率,可以用DP[I][J]表示J轮后,I获胜的概率,J至多为7。

转移时只需要枚举另一队伍K,计算I继续获胜的概率

DP[I][J]=DP[I][J-1]*ΣDP[K][J-1]*P[I][K]

判断K是否会和I在恰好J轮后相遇,可以用位操作进行判断,如果学过ZKW线段树,可以很容易写出条件:

if(((i+m-1)>>j)==((k+m-1)>>j)&&((i+m-1)>>(j-1))!=((k+m-1)>>(j-1)))

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdlib.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<bitset>
#pragma comment(linker, "/STACK:1024000000,1024000000")
template <class T>
bool scanff(T &ret){ //Faster Input
char c; int sgn; T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n'){ ret*=sgn; return 1; }
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
#define inf 1073741823
#define llinf 4611686018427387903LL
#define PI acos(-1.0)
#define lth (th<<1)
#define rth (th<<1|1)
#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)
#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)
#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)
#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)
#define mem(x,val) memset(x,val,sizeof(x))
#define mkp(a,b) make_pair(a,b)
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

int n,m;

double dp[129][8];
double p[129][129];
int main(){
while(scanf("%d",&n)!=EOF){
if(n==-1)break;
m=1<<n;
rep(i,1,m)
rep(j,1,m){
scanf("%lf",&p[i][j]);
}
mem(dp,0);
rep(i,1,m)dp[i][0]=1.0;
rep(j,1,n){
rep(i,1,m){
rep(k,1,m){
if(((i+m-1)>>j)==((k+m-1)>>j)&&((i+m-1)>>(j-1))!=((k+m-1)>>(j-1))){
//如果I和K在第J轮可能进行比赛
dp[i][j]+=dp[i][j-1]*dp[k][j-1]*p[i][k];
}
}
}
}
double maxx=-1;
int ans=-1;
rep(i,1,m){
if(dp[i]
>maxx){
maxx=dp[i]
;
ans=i;
}
}
printf("%d\n",ans);
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: