POJ 3071 Football 【概率DP】
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 3734 | Accepted: 1908 |
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.
Input
The input test file will contain multiple test cases. Each test case will begin with a single line containing n (1 ≤ n ≤ 7). The next 2n lines each contain 2n values; here, the jth value
on the ith line represents pij. The matrix P will satisfy the constraints that pij = 1.0 − pji for all i ≠ j, and pii = 0.0 for all i.
The end-of-file is denoted by a single line containing the number −1. Note that each of the matrix entries in this problem is given as a floating-point value. To avoid precision problems, make sure that you use either the double data type instead
of float.
Output
The output file should contain a single line for each test case indicating the number of the team most likely to win. To prevent floating-point precision issues, it is guaranteed that the difference in win probability for the top two teams will be at least
0.01.
Sample Input
2
0.0 0.1 0.2 0.3
0.9 0.0 0.4 0.5
0.8 0.6 0.0 0.6
0.7 0.5 0.4 0.0
-1
Sample Output
2
Hint
In the test case above, teams 1 and 2 and teams 3 and 4 play against each other in the first round; the winners of each match then play to determine the winner of the tournament. The probability that team 2 wins the tournament in this case is:
| P(2 wins) | = P(2 beats 1)P(3 beats 4)P(2 beats 3) + P(2 beats 1)P(4 beats 3)P(2 beats 4) = p21p34p23 + p21p43p24 = 0.9 · 0.6 · 0.4 + 0.9 · 0.4 · 0.5 = 0.396. |
The next most likely team to win is team 3, with a 0.372 probability of winning the tournament.
题意:这个题是给你一个2^N的一个概率矩阵p , p[i][j]用来表示第i队赢第j队的概率。足球比赛是依据编号由小到大来两两比赛的,问你最有可能最后赢的队伍编号。
分析:队伍两两之间进行比赛,直到得到Winner。这个过程是须要N层比赛的【我想不出什么高级的词汇了。就用层来说吧。语文不好,不要嘲笑~】,每一层有若干双 队伍 同一时候进行比赛。然后是依据编号两两比赛的。这个时候最好还是画出一个图出来,我们能够发现,这就是一个二叉树嘛。
首先。设状态 dp[i][j] 表示第i层比赛第j号队伍赢的概率。
然后,设状态转移方程:dp[i][j] = dp[i-1][j] * ∑(dp[i-1][k]*p[j][k]),ps:k∈(二叉树上(i,j)除了(i-1。j)的另外一个子节点下面的全部叶子节点的编号)。说得确实有点拗口,可是仅仅要画出图来。就很好理解。
接下来,考虑边界情况,显然dp[0][j] = 0。或者说dp[1][j] = p[j][(j-1)^1+1] 【第二种写法是dp[i][j] = p[j][j&1?
j+1:j-1],用哪种凭个人喜好吧】,j∈(1,1<<N)。
最后。仅仅须要遍历全部dp[N][j] ,j∈(1,1<<N),求最大的概率就可以。
/**
* Memory:444KB Time:79ms
* Author:__Xiong 2015/7/27
*/
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 7+1;
const int maxm = (1<<maxn);
int N,M,ans;
double pMax,p[maxm][maxm],dp[maxn][maxm];
int main()
{
//freopen("input.in","r",stdin);
while(~scanf("%d",&N))
{
if(N == -1) break;
M = (1<<N);
for(int i = 1; i <= M; i++)
{
for(int j = 1; j <= M; j++)
{
scanf("%lf",&p[i][j]);
}
}
memset(dp,0,sizeof(dp));
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= M; j++)
{
if(i == 1)
{
dp[1][j] = p[j][j&1?j+1:j-1];
continue;
}
for(int k = 1; k <= M; k++)
{
int a = (j-1)>>(i-1),b = (k-1)>>(i-1);
if(a&1) a--;
else a++;
if(a == b)
dp[i][j] += dp[i-1][j]*dp[i-1][k]*p[j][k];
}
}
}
pMax = 0;
ans = 0;
for(int i = 1; i <= M; i++)
{
if(pMax < dp[N][i])
{
ans = i;
pMax = dp[N][i];
}
}
printf("%d\n",ans); }
return 0;
}
另外。挂上基神的代码吧。
// 亲測:Memory:1080KB Time:79ms
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MX = 150 + 5;
#define For(i,x,y) for(int i=x;i<=y;i++)
#define Mem(x,y) memset(x,y,sizeof(x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 1,n,1
int n;
double A[MX][MX];
double dp[MX << 2][MX];
void solve(int l, int r, int rt)
{
if(l == r)
{
dp[rt][l] = 1;
return;
}
int m = (l + r) >> 1;
solve(lson);
solve(rson);
For(x, l, r)
{
if(x <= m)
{
For(i, m + 1, r)
{
dp[rt][x] += dp[rt << 1 | 1][i] * A[x][i];
}
dp[rt][x] *= dp[rt << 1][x];
}
else
{
For(i, l, m)
{
dp[rt][x] += dp[rt << 1][i] * A[x][i];
}
dp[rt][x] *= dp[rt << 1 | 1][x];
}
}
}
int main()
{
//freopen("input.in", "r", stdin);
int n;
while(~scanf("%d", &n), n >= 0)
{
Mem(dp, 0);
n = 1 << n;
For(i, 1, n)
{
For(j, 1, n)
{
scanf("%lf", &A[i][j]);
}
}
solve(root);
double Max = 0;
int ans;
For(i, 1, n)
{
if(dp[1][i] > Max)
{
Max = dp[1][i];
ans = i;
}
}
printf("%d\n", ans);
}
return 0;
}
POJ 3071 Football 【概率DP】的更多相关文章
- poj 3071 Football (概率DP水题)
G - Football Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit ...
- POJ 3071 Football(概率DP)
题目链接 不1Y都对不住看过那么多年的球.dp[i][j]表示i队进入第j轮的概率,此题用0-1<<n表示非常方便. #include <cstdio> #include &l ...
- poj 3071 Football(概率dp)
id=3071">http://poj.org/problem? id=3071 大致题意:有2^n个足球队分成n组打比赛.给出一个矩阵a[][],a[i][j]表示i队赢得j队的概率 ...
- POJ 3071 Football (概率DP)
概率dp的典型题.用dp[j][i]表示第j个队第i场赢的概率.那么这场要赢就必须前一场赢了而且这一场战胜了可能的对手.这些都好想,关键是怎么找出当前要算的队伍的所有可能的竞争对手?这个用异或来算,从 ...
- POJ 3071 Football
很久以前就见过的...最基本的概率DP...除法配合位运算可以很容易的判断下一场要和谁比. from——Dinic算法 Football Time ...
- POJ3071:Football(概率DP)
Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, …, 2 ...
- POJ 3156 - Interconnect (概率DP+hash)
题意:给一个图,有些点之间已经连边,现在给每对点之间加边的概率是相同的,问使得整个图连通,加边条数的期望是多少. 此题可以用概率DP+并查集+hash来做. 用dp(i,j,k...)表示当前的每个联 ...
- poj 1322 Chocolate (概率dp)
///有c种不同颜色的巧克力.一个个的取.当发现有同样的颜色的就吃掉.去了n个后.到最后还剩m个的概率 ///dp[i][j]表示取了i个还剩j个的概率 ///当m+n为奇时,概率为0 # inclu ...
- [poj3071]football概率dp
题意:n支队伍两两进行比赛,求最有可能获得冠军的队伍. 解题关键:概率dp,转移方程:$dp[i][j] + = dp[i][j]*dp[i][k]*p[j][k]$表示第$i$回合$j$获胜的概率 ...
- POJ 3071 Football:概率dp
题目链接:http://poj.org/problem?id=3071 题意: 给定n,有2^n支队伍参加足球赛. 给你所有的p[i][j],表示队伍i打败队伍j的概率. 淘汰赛制.第一轮(1,2)两 ...
随机推荐
- Django admin 界面无法加载 CSS 问题解决方案(服务器 Apache 服务器)
主要原因: 未找到存放静态文件的目录 没有访问目录的权限 基础知识: 在 CentOS 下面,Django 的静态文件存放在目录: /usr/lib/python2./site-packages/dj ...
- [BZOJ1176][Balkan2007]Mokia cdq+树状数组
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 3134 Solved: 1395[Submit][S ...
- Nodejs微信与Bot framework通过Direct Line连接
背景 最近开发了一个Bot Framework的小工具,能够通过Luis分析出用户输入的文本,对文本中的StyleNo/FabricNo/TrimNo提取出来,并传入另一个小系统进行查询出结果,包括文 ...
- java 访问 kerberos 认证的 kafka
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- vim 代码片段:通过vundle插件管理器安装ultisnips |centos6.5|vim7.2
背景:中午醒来,饭都没吃,突然想到要给vim增加个代码片段的功能,因为昨天使用了gedit的代码片段,感觉不错.为什么不直接使用gedit呢?因为我相信把时间投入到vim是不会错的,精通vim就好了. ...
- POJ 3126 Prime Path【从一个素数变为另一个素数的最少步数/BFS】
Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 26475 Accepted: 14555 Descript ...
- HDU 1285 确定比赛名次【字典序最小的拓扑排序 + 优先队列】
确定比赛名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- 训练指南 UVALive - 5135 (双连通分量)
layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...
- rsync用于同步目录
rsync是unix/linux下同步文件的一个高效算法,它能同步更新两处计算机的文件与目录,并适当利用查找文件中的不同块以减少数据传输.rsync中一项与其他大部分类似程序或协定中所未见的重要特性是 ...
- [BZOJ2125]最短路(圆方树DP)
题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...