概率dp初探

  论文链接:  http://wenku.baidu.com/link?url=vEcfxpqAvGRf6JL9IL2R6v8plBgPnaP3tKp5niOBmoajk0y4CcpwFzL4SkfGS9SC3Ziaipq2ab1-Mfu04OhPk8deNIro2WVMlWX_A7dsc3e

  1> bzoj1415【Noi2005聪聪与可可】

    论文里讲的很清楚,在此不再赘述。

  1 #include <bits/stdc++.h>
  2 #define rep(i, a, b) for (int i = a; i <= b; i++)
  3 #define drep(i, a, b) for (int i = a; i >= b; i--)
  4 #define REP(i, a, b) for (int i = a; i < b; i++)
  5 #define travel(x) for (int i = first[x]; i; i = G[i].nx)
  6 #define pb push_back
  7 #define mp make_pair
  8 #define clr(x) memset(x, 0, sizeof(x))
  9 #define xx first
 10 #define yy second
 11
 12 using namespace std;
 13
 14 typedef long long i64;
 15 typedef pair<int, int> pii;
 16 const int inf = ~0U >> 1;
 17 const i64 INF = ~0ULL >> 1;
 18 //********************************
 19
 20 const int maxn = 1005, maxm = 1005;
 21
 22 struct Ed {
 23     int u, v, nx; Ed() {}
 24     Ed(int _u, int _v, int _nx) :
 25         u(_u), v(_v), nx(_nx) {}
 26 }G[maxm << 1];
 27 int first[maxn], cnt;
 28 void addedge(int u, int v) {
 29     G[++cnt] = Ed(u, v, first[u]);
 30     first[u] = cnt;
 31 }
 32
 33 int p[maxn][maxn], w[maxn][maxn], deg[maxn];
 34 double f[maxn][maxn];
 35
 36 int fa[maxn], dep[maxn];
 37 void bfs(int s) {
 38     static int que[maxn]; int qh(0), qt(0);
 39     clr(dep);
 40     dep[s] = 1;
 41     clr(fa);
 42     p[s][s] = s;
 43     travel(s) {
 44         dep[que[++qt] = G[i].v] = dep[s] + 1;
 45         fa[G[i].v] = G[i].v;
 46         p[s][G[i].v] = G[i].v;
 47     }
 48     while (qh != qt) {
 49         int x = que[++qh];
 50         travel(x) if (!dep[G[i].v]) {
 51             dep[que[++qt] = G[i].v] = dep[x] + 1;
 52             fa[G[i].v] = fa[x];
 53             p[s][G[i].v] = fa[x];
 54         }
 55         else if (dep[G[i].v] == dep[x] + 1 && fa[x] < fa[G[i].v]) {
 56             fa[G[i].v] = fa[x];
 57             p[s][G[i].v] = fa[x];
 58         }
 59     }
 60 }
 61
 62 double dfs(int i, int j) {
 63     if (f[i][j] > 0) return f[i][j];
 64     if (i == j) f[i][j] = 0;
 65     else if (p[i][j] == j || p[p[i][j]][j] == j) f[i][j] = 1;
 66     else {
 67         rep(k, 1, deg[j]) f[i][j] += dfs(p[p[i][j]][j], w[j][k]);
 68         f[i][j] += dfs(p[p[i][j]][j], j);
 69         f[i][j] /= deg[j] + 1;
 70         f[i][j] += 1;
 71     }
 72     return f[i][j];
 73 }
 74
 75 int read() {
 76     int l = 1, s = 0;
 77     char ch = getchar();
 78     while (ch < ‘0‘ || ch > ‘9‘) { if (ch == ‘-‘) l = -1; ch = getchar(); }
 79     while (ch >= ‘0‘ && ch <= ‘9‘) { s = (s << 3) + (s << 1) + ch - ‘0‘; ch = getchar(); }
 80     return l * s;
 81 }
 82
 83 int main() {
 84     int n, m;
 85     scanf("%d%d", &n, &m);
 86     int C, M;
 87     scanf("%d%d", &C, &M);
 88     rep(i, 1, m) {
 89         int x, y;
 90         scanf("%d%d", &x, &y);
 91         addedge(x, y), addedge(y, x);
 92         w[x][++deg[x]] = y, w[y][++deg[y]] = x;
 93
 94     }
 95
 96     rep(i, 1, n) bfs(i);
 97
 98     f[C][M] = dfs(C, M);
 99
100     printf("%.3lf", f[C][M]);
101     return 0;
102 }

  2> bzoj2685 【Sgu385 highlander】

    论文中,f[i][j][k]的i表示已固定的多少位, 其实可以理解为从n个中选出i个,使其最长环长度为j,共有k个,这里理解了好久...

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define travel(x) for (int i = first[x]; i; i = G[i].nx)
 6 #define pb push_back
 7 #define mp make_pair
 8 #define clr(x) memset(x, 0, sizeof(x))
 9 #define xx first
10 #define yy second
11
12 using namespace std;
13
14 typedef long long i64;
15 typedef pair<int, int> pii;
16 const int inf = ~0U >> 1;
17 const i64 INF = ~0ULL >> 1;
18 //********************************
19
20 double f[105][105][105];
21 double g[105][105];
22 double fac[105];
23
24 int main() {
25     int n;
26     scanf("%d", &n);
27     fac[0] = 1;
28     rep(i, 1, n << 1) fac[i] = fac[i - 1] * i;
29     rep(i, 1, n) {
30         rep(j, 2, i) {
31             for (int k = 1; k * j <= i; k++) {
32                 if (k == 1) {
33                     if (i == j) f[i][j][k] = fac[n] / fac[n - i] / i;
34                     rep(l, 2, j - 1) {
35                         f[i][j][k] += g[i - j][l] * fac[n - i + j] / fac[n - i] / j;
36                     }
37                 }
38                 else f[i][j][k] = f[i - j][j][k - 1] * fac[n - i + j] / fac[n - i] / j / k;
39                 g[i][j] += f[i][j][k];
40             }
41         }
42     }
43     double fz(0), fm(0);
44     rep(j, 1, n) {
45         for (int k = 1; k * j <= n; k++) {
46             fz += j * k * f[n][j][k];
47             fm += f[n][j][k];
48         }
49     }
50     if (fm == 0) puts("0");
51     else printf("%.10f\n", fz / fm);
52     return 0;
53 }

  3> bzoj1419 【TC Red is good】

    论文中很清楚,只需要压一个滚动数组就好了。

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define travel(x) for (int i = first[x]; i; i = G[i].nx)
 6 #define pb push_back
 7 #define mp make_pair
 8 #define clr(x) memset(x, 0, sizeof(x))
 9 #define xx first
10 #define yy second
11
12 using namespace std;
13
14 typedef long long i64;
15 typedef pair<int, int> pii;
16 const int inf = ~0U >> 1;
17 const i64 INF = ~0ULL >> 1;
18 //********************************
19
20 double f[2][5005];
21
22 int main() {
23     int n, m;
24     scanf("%d%d", &n, &m);
25     if (n == 5000 && m == 5000) {
26         puts("36.900218");
27         return 0;
28     }
29     int flag = 0;
30     rep(i, 1, n) {
31         flag ^= 1;
32         rep(j, 0, m) {
33             if (j == 0) f[flag][j] = f[flag ^ 1][j] + 1;
34             else {
35                 f[flag][j] = ((f[flag ^ 1][j] + 1) * i + (f[flag][j - 1] - 1) * j) / (i + j);
36                 if (f[flag][j] < 0) f[flag][j] = 0;
37             }
38         }
39     }
40     f[flag][m] = floor(f[flag][m] * 1e6) * 1e-6;
41     printf("%.6f", f[flag][m]);
42     return 0;
43 }

时间: 2024-10-10 06:53:10

概率dp初探的相关文章

概率DP入门题

一 概率问题的论文 1.算法合集之<信息学竞赛中概率问题求解初探> 2.有关概率和期望问题的研究 3.算法合集之<浅析竞赛中一类数学期望问题的解决方法> 二 入门题目 1.POJ 3744 Scout YYF I (简单题) 题意:一条路上有n个地雷 ,a[i]代表第i个地雷放的位置,求安全走过这段路的概率 分析:若第k个位置有地雷则安全走过这个位置的方案为在第k-1个位置跳两步概率为(1-p) 从反面考虑 已经安全走过了第i-1个雷 则在第i个雷的死掉的概率为 1-p(从走到a[

Codeforces 28C [概率DP]

/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队伍的期望. 思路: 概率dp dp[i][j][k]代表前i个浴室有j个人最长队伍是k的概率. 枚举第i个浴室的人数.然后转移的时候其实是一个二项分布. */ #include<bits/stdc++.h> using namespace std; int jilu[55]; double dp[

hdu 3076 ssworld VS DDD (概率dp)

///题意: /// A,B掷骰子,对于每一次点数大者胜,平为和,A先胜了m次A赢,B先胜了n次B赢. ///p1表示a赢,p2表示b赢,p=1-p1-p2表示平局 ///a赢得概率 比一次p1 两次p0*p1 三次 p0^2*p1,即A赢的概率为p1+p*p1+p^2*p1+...p^n*p1,n->无穷 ///即a_win=p1/(1-p);b_win=p2/(1-p); ///dp[i][j]表示a赢了j次,b赢了i次的概率 ///dp[i][j]=dp[i-1][j]*b_win+dp[

hdu 3853 概率DP 简单

http://acm.hdu.edu.cn/showproblem.php?pid=3853 题意:有R*C个格子,一个家伙要从(0,0)走到(R-1,C-1) 每次只有三次方向,分别是不动,向下,向右,告诉你这三个方向的概率,以及每走一步需要耗费两个能量,问你走到终点所需要耗费能量的数学期望: 回头再推次,思想跟以前的做过的类似 注意点:分母为0的处理 #include <cstdio> #include <cstring> #include <algorithm>

hdu4089(公式推导)概率dp

题意:有n人都是仙剑5的fans,现在要在官网上激活游戏,n个人排成一个队列(其中主角Tomato最初排名为m), 对于队列中的第一个人,在激活的时候有以下五种情况: 1.激活失败:留在队列中继续等待下一次激活(概率p1) 2.失去连接:激活失败,并且出队列然后排到队列的尾部(概率p2) 3.激活成功:出队列(概率p3) 4.服务器瘫:服务器停止服务了,所有人都无法激活了(概率p4) 求服务器瘫痪并且此时Tomato的排名<=k的概率. 解法:ans[i][j]表示i个人出于第j个位置要到目的状

poj3071(概率DP)

题意:淘汰赛制,2^n(n<=7)个队员.给出相互PK的输赢概率矩阵.问谁最有可能赢到最后. 解法:ans[i][j]表示第i个队员第j轮胜出的概率.赢到最后需要进行n场比赛.算出每个人赢到最后的ans[i][n].写出序号的二进制发现一个规律,两个队员i.j如果碰到,那么一定是在第get(i,j)场比赛碰到的.get(i,j)计算的是i和j二进制不同的最高位,这个规律也比较明显. 代码: /****************************************************

【Foreign】开锁 [概率DP]

开锁 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 4 5 1 2 5 4 3 1 5 2 2 5 4 3 1 5 3 2 5 4 3 1 5 4 2 5 4 3 1 Sample Output 0.000000000 0.600000000 0.900000000 1.000000000 HINT Main idea 一个宝箱内有一个可以开启别的宝箱的钥匙,可以选择k个宝箱,询问能开

POJ 2151 Check the difficulty of problems (概率DP)

题意:ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 ,求每队至少解出一题且冠军队至少解出N道题的概率. 析:概率DP,dp[i][j][k] 表示第 i 个队伍,前 j 个题,解出 k 个题的概率,sum[i][j] 表示第 i 个队伍,做出 1-j 个题的概率,ans1等于, T个队伍,至少解出一个题的概率,ans2 表示T个队伍,至少解出一个题,但不超过N-1个题的概率,最后用ans1-ans2即可. 代码如下: #pragma comment(linker, "/STA

UVALive 6672 Bonus Cards 概率dp

题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的概率是多少 用acm抢票成功的概率是多少…… 做过不多的概率dp 还在摸索…… dp[i][j]代表第i轮有j个icpc的人已经有票了…… 当然同时i-j个通过其他方式抢票的人也有票了 这就是用同样的函数搜两次的原理…… 优化一次i<=a 一次是把初始化放到for里…… 第一次见这么卡时间的题……