BZOJ1778 [Usaco2010 Hol]Dotp 驱逐猪猡
2015-05-23 08:22
344 查看
首先我们列出转移矩阵$M$,$M_{i, j} = \frac {1 - \frac{p} {q}} {deg[i]}$(i,j之间有边)or $M_{i, j} = 0$(i,j之间没边)
则这个矩阵$M_{i, j}$表示的是站在某个点$i$,下一次走到$j$且没有爆炸的概率
我们再看$M^n_{i, j}$,表示的站在某个点$i$,走$n$步以后到达$j$且没有爆炸的概率
故$M^n$的第一列代表了$1$号点到其他所有点的概率,设为列向量$A_n$,则$A_n = M^n * B$,其中$B = (1, 0, 0, 0, ...)^T$
设第n步到各点且爆炸了的概率的列向量为$P_n$,则$P_n = \frac{p} {q} * A_n$
故答案列向量$Ans = \sum_{i = 0} ^ {+\infty} P_i$
把它展开:$Ans = \frac{p} {q} * (\sum_{i = 0} ^ {+\infty} M^i) * B$
由等比数列求和公式,$\sum_{i = 0} ^ {+\infty} M^i = \frac{I} {I - M} = (I - M)^{-1}$
故$Ans = \frac{p} {q} * (I - M)^{-1} * B$,即$(I- M) * Ans = \frac{p} {q} * B$
得到一个线性方程组,我们只要高斯消元即可
View Code
则这个矩阵$M_{i, j}$表示的是站在某个点$i$,下一次走到$j$且没有爆炸的概率
我们再看$M^n_{i, j}$,表示的站在某个点$i$,走$n$步以后到达$j$且没有爆炸的概率
故$M^n$的第一列代表了$1$号点到其他所有点的概率,设为列向量$A_n$,则$A_n = M^n * B$,其中$B = (1, 0, 0, 0, ...)^T$
设第n步到各点且爆炸了的概率的列向量为$P_n$,则$P_n = \frac{p} {q} * A_n$
故答案列向量$Ans = \sum_{i = 0} ^ {+\infty} P_i$
把它展开:$Ans = \frac{p} {q} * (\sum_{i = 0} ^ {+\infty} M^i) * B$
由等比数列求和公式,$\sum_{i = 0} ^ {+\infty} M^i = \frac{I} {I - M} = (I - M)^{-1}$
故$Ans = \frac{p} {q} * (I - M)^{-1} * B$,即$(I- M) * Ans = \frac{p} {q} * B$
得到一个线性方程组,我们只要高斯消元即可
/************************************************************** Problem: 1778 User: rausen Language: C++ Result: Accepted Time:200 ms Memory:2264 kb ****************************************************************/ #include <cstdio> #include <cmath> #include <algorithm> using namespace std; typedef double lf; const int N = 305; const int M = N * N; inline int read(); struct edge { int next, to; edge() {} edge(int _n, int _t) : next(_n), to(_t) {} } e[M]; int n, m, deg ; int first , tot; lf P, a , ans ; inline void Add_Edges(int x, int y) { e[++tot] = edge(first[x], y), first[x] = tot; e[++tot] = edge(first[y], x), first[y] = tot; ++deg[x], ++deg[y]; } #define y e[x].to inline void build_matrix() { int p, x; for (p = 1; p <= n; ++p) { for (x = first[p]; x; x = e[x].next) a[p][y] = -(1.0 - P) / deg[y]; a[p][p] = 1; } a[1][n + 1] = P; } #undef y void gauss(int n) { int i, j, k; lf tmp; for (i = 1; i <= n; ++i) { for (k = i, j = i + 1; j <= n; ++j) if (fabs(a[j][i]) > fabs(a[k][i])) k = j; for (j = i; j <= n + 1; ++j) swap(a[i][j], a[k][j]); for (k = i + 1; k <= n; ++k) for (tmp = -a[k][i] / a[i][i], j = i; j <= n + 1; ++j) a[k][j] += a[i][j] * tmp; } for (i = n; i; --i) { for (j = i + 1; j <= n; ++j) a[i][n + 1] -= a[i][j] * ans[j]; ans[i] = a[i][n + 1] / a[i][i]; } } int main() { int i, j; n = read(), m = read(), P = 1.0 * read() / read(); for (i = 1; i <= m; ++i) Add_Edges(read(), read()); build_matrix(); gauss(n); for (i = 1; i <= n; ++i) printf("%.9lf\n", ans[i]); return 0; } inline int read() { static int x; static char ch; x = 0, ch = getchar(); while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x; }
View Code
相关文章推荐
- BZOJ 1778 [Usaco2010 Hol]Dotp 驱逐猪猡 ——期望DP
- BZOJ1778: [Usaco2010 Hol]Dotp 驱逐猪猡
- 【BZOJ1778】[Usaco2010 Hol]Dotp 驱逐猪猡 期望DP+高斯消元
- 【BZOJ】1778: [Usaco2010 Hol]Dotp 驱逐猪猡
- BZOJ 1778 Usaco2010 Hol Dotp 驱逐猪猡 期望DP+高斯消元
- bzoj1778: [Usaco2010 Hol]Dotp 驱逐猪猡(概率DP+高斯消元)
- BZOJ1778 [Usaco2010 Hol]Dotp 驱逐猪猡
- BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡
- BZOJ_1778_[Usaco2010_Hol]_Dotp_驱逐猪猡_(期望动态规划+高斯消元+矩阵)
- BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡
- BZOJ1778: [Usaco2010 Hol]Dotp 驱逐猪猡
- BZOJ 1778 [Usaco2010 Hol] Dotp 驱逐猪猡
- 【BZOJ1778】[Usaco2010 Hol]Dotp 驱逐猪猡【概率DP】【高斯消元】
- [BZOJ 1778][Usaco2010 Hol]Dotp 驱逐猪猡
- BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡 [高斯消元 概率DP]
- bzoj 1778: [Usaco2010 Hol]Dotp 驱逐猪猡【dp+高斯消元】
- bzoj 1778 [Usaco2010 Hol]Dotp 驱逐猪猡(高斯消元)
- bzoj 1778 [Usaco2010 Hol]Dotp 驱逐猪猡 高斯消元
- BZOJ_1778_[Usaco2010 Hol]Dotp 驱逐猪猡_概率DP+高斯消元
- 【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元