poj 3071 概率dp

//分析:明显的树形关系,题目描述的是一棵高 n + 1的完全二叉树,则 dp[树层号][team号](规定最底层为 0 层,层数朝节点的方向依次递增),推一下就好了

//稍微需要想一下的是比赛双方的选取,下面给出两种方法

//#1 枚举起点划分team区间

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "algorithm"
 5 using namespace std;
 6 double dp[10][130], mat[130][130];
 7 int n;
 8
 9 int main()
10 {
11     int i, j, k, t;
12     while(scanf("%d", &n) && (n != -1)) {
13         for(i = 1; i <= (1 << n); ++i)
14             for(j = 1; j <= (1 << n); ++j)
15                 scanf("%lf", &mat[i][j]);
16         memset(dp, 0, sizeof(dp));
17         int tot = 1 << n, half;
18         for(i = 1; i <= tot; ++i)
19             dp[0][i] = 1;
20         for(i = 1; i <= n; ++i) {
21             tot = 1 << i, half = 1 << (i - 1);
22             for(j = 1; j <= (1 << n); j += tot) {
23                 for(k = j; k <= j + half - 1; ++k) {
24                     for(t = j + half; t <= j + tot - 1; ++t) {
25                         dp[i][k] += dp[i - 1][k] * dp[i - 1][t] * mat[k][t];
26                         dp[i][t] += dp[i - 1][k] * dp[i - 1][t] * mat[t][k];
27                     }
28                 }
29             }
30         }
31         double ans = 0;
32         int res = 1;
33         for(i = 1; i <= (1 << n); ++i)
34             if(ans < dp[n][i])
35                 ans = dp[n][i], res = i;
36         printf("%d\n", res);
37     }
38 }

//#2 比较向上 i - 1 层的根节点序号(存在提前相遇情况)

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "algorithm"
 5 using namespace std;
 6 double dp[10][130], mat[130][130];
 7 int n;
 8
 9 int main()
10 {
11     int i, j, k;
12     while(scanf("%d", &n) && (n != -1)) {
13         for(i = 1; i <= (1 << n); ++i)
14             for(j = 1; j <= (1 << n); ++j)
15                 scanf("%lf", &mat[i][j]);
16         memset(dp, 0, sizeof(dp));
17         for(i = 1; i <= (1 << n); ++i)
18             dp[0][i] = 1;
19         for(i = 1; i <= n; ++i) {
20             for(j = 1; j <= (1 << n); ++j) {
21                 for(k = 1; k <= (1 << n); ++k) {
22                     int root_j = (j - 1) >> (i - 1), root_k = (k - 1) >> (i - 1);
23                     if(root_j != root_k && (root_j >> 1) == (root_k >> 1)) {    //向上 i - 1 层的根节点不同 且 是同一节点的左右孩子
24                         dp[i][j] += dp[i - 1][j] * dp[i - 1][k] * mat[j][k];
25                         dp[i][k] += dp[i - 1][j] * dp[i - 1][k] * mat[k][j];
26                     }
27                 }
28             }
29         }
30         int res = 1;
31         double ans = 0;
32         for(i = 1; i <= (1 << n); ++i)
33             if(ans < dp[n][i])
34                 ans = dp[n][i], res = i;
35         printf("%d\n", res);
36     }
37 }
时间: 2024-11-07 20:57:18

poj 3071 概率dp的相关文章

poj 3071 概率DP 位运算

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Practice POJ 3071 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, …, 2n. In each round of the tournament, all tea

poj 2151 概率dp

//poj 2151 概率dp 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 double dp[33][33]; 7 int M, T, N; //problem, team, least 8 double p[1010][33]; 9 int mai

POJ 3701 概率DP

给定2^n 支足球队进行比赛,n<=7. 队伍两两之间有一个获胜的概率,求每一个队伍赢得最后比赛的概率是多少? 状态其实都是很显然的,一开始觉得这个问题很难啊,不会.dp[i][j] 表示第i支队伍赢得前j轮比赛的概率.(这个题目处理区间的时候比较恶心,小心点即可). 1:   2: #include <iostream> 3: #include <cstdio> 4: #include <cstring> 5: #include <map> 6: #

poj 2096 (概率DP)

http://poj.org/problem?id=2096 概率DP: 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 double dp[1003][1003]; 5 int main() 6 { 7 int n,s,i,j; 8 cin>>n>>s; 9 for (i=n;i>=0;i--) 10 { 11 for (j=s;j>=0;j--) 12 { 13

poj 3744 概率dp+矩阵快速幂

题意:在一条布满地雷的路上,你现在的起点在1处.在N个点处布有地雷,1<=N<=10.地雷点的坐标范围:[1,100000000]. 每次前进p的概率前进一步,1-p的概率前进1-p步.问顺利通过这条路的概率.就是不要走到有地雷的地方. 设dp[i]表示到达i点的概率,则 初始值 dp[1]=1. 很容易想到转移方程: dp[i]=p*dp[i-1]+(1-p)*dp[i-2]; 但是由于坐标的范围很大,直接这样求是不行的,而且当中的某些点还存在地雷. N个有地雷的点的坐标为 x[1],x[2

Check the difficulty of problems - poj 2151 (概率+DP)

有 T(1<T<=1000) 支队伍和 M(0<M<=30) 个题目,已知每支队伍 i 解决每道题目 j 的的概率 p[i][j],现在问:每支队伍至少解决一道题,且解题最多的队伍的题目数量不少于 N(0<N<=M) 的概率是多少? p[i][j]表示第i个队伍做对第j题的概率.dp[i][j][k]表示第i个队伍在前j题中做对了k道的概率.dp[i][j][k] = dp[i][j-1][k-1]*(p[i][j])+dp[i][j-1][k]*(1-p[i][j])

poj 3744 概率dp 矩阵快速幂优化

一位童子兵要穿过一条路,路上有些地方放着地雷.这位童子兵非常好玩,走路一蹦一跳的.每次他在 i 位置有 p 的概率走一步到 i+1 ,或者 (1-p) 的概率跳一步到 i+2.童子兵初始在1位置,求他安全通过这条道路的概率. 以所在位置为状态,dp[i] 表示在位置 i 的安全的概率. dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; // i 位置没有地雷 但是题目数据的范围是 10^8 这样dp的话会 TLE. 想想可以用矩阵快速幂优化.简单退出矩阵是 |p

Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)

题意: 一条路上有n个地雷,你从1开始走,单位时间内有p的概率走一步,1-p的概率走两步,问安全通过这条路的概率 解析: 很容易想到 dp[i] = p * dp[i-1] + (1 - p) * dp[i]; 然而...t,但这个式子明显可以用矩阵快速幂加个氮气一下加速一下... 把所有的点输入之后 sort一下,那么就能把这条路分成很多段 每一段以地雷为分界线 1 - x[0]  x[0]+1 - x[1]  x[1]+1 - x[2] ````````` 然后求出安全通过每一段的概率  

poj 3071 Football DP

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3297   Accepted: 1687 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