BZOJ 3640: JC的小苹果 [概率DP 高斯消元 矩阵求逆]
2017-04-02 23:41
435 查看
3640: JC的小苹果
题意:求1到n点权和\(\le k\)的概率sengxian orz的题解好详细啊
容易想到\(f[i][j]\)表示走到i点权为j的概率
按点权分层,可以DP
但是对于\(val[i]=0\)的点,就不是DAG了,必须使用高斯消元
每层消元一次?复杂度\(O(SN^3)\),boom!!!
发现每次的系数矩阵一样啊
\[ Ax=b \rightarrow x=A^{-1}b \]
我们求出\(A\)矩阵的逆,然后直接让常数向量乘逆就可以了,因为常数矩阵是向量,一次的复杂度\(O(N^2)\)
然后就可以\(O(SN^2)\)了
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; typedef unsigned long long ll; const int N=155, M=1e4+5; const double eps=1e-8; inline int read() { char c=getchar(); int x=0, f=1; while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();} while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();} return x*f; } int n, m, s, val , u, v; struct edge{int v, ne;}e[M]; int cnt=1, h , de ; inline void ins(int u, int v) { e[++cnt]=(edge){v, h[u]}; h[u]=cnt; } struct Matrix { double a ; Matrix() {memset(a, 0, sizeof(a));} double* operator [](int x) {return a[x];} void im() {for(int i=1; i<=n; i++) a[i][i]=1;} void print() {for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) printf("%lf%c",a[i][j], j==n?'\n':' ');puts("");} }a, c; Matrix inverse(Matrix a) { Matrix c; c.im(); for(int i=1; i<=n; i++) { int r=i; for(int j=i; j<=n; j++) if(abs(a[j][i])>abs(a[r][i])) r=j; if(r!=i) for(int j=1; j<=n; j++) swap(a[i][j], a[r][j]), swap(c[i][j], c[r][j]); double t = a[i][i]; for(int j=1; j<=n; j++) a[i][j]/=t, c[i][j]/=t; for(int k=1; k<=n; k++) if(k!=i) { double t = a[k][i]; for(int j=1; j<=n; j++) a[k][j] -= t*a[i][j], c[k][j] -= t*c[i][j]; } } return c; } double b , f [M]; void dp() { double ans=0; for(int now=s; now>0; now--){ memset(b, 0, sizeof(b)); if(now==s) b[1]=1; for(int u=1; u<=n; u++) if(val[u] && now+val[u]<=s) for(int i=h[u];i;i=e[i].ne) if(e[i].v != n) b[u] += f[e[i].v][now+val[u]] / de[e[i].v]; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) f[i][now] += a[i][j] * b[j]; ans += f [now]; } printf("%.8lf", ans); } int main() { freopen("in","r",stdin); n=read(); m=read(); s=read(); for(int i=1; i<=n; i++) val[i]=read(); for(int i=1; i<=m; i++) { u=read(); v=read(); ins(u, v); de[u]++; if(u!=v) ins(v, u), de[v]++; } for(int u=1; u<=n; u++) { a[u][u]=1; if(!val[u]) for(int i=h[u];i;i=e[i].ne) if(e[i].v != n) a[u][e[i].v] -= 1.0/de[e[i].v]; } a = inverse(a); dp(); }
相关文章推荐
- [BZOJ3640]JC的小苹果(概率dp+高斯消元)
- 【BZOJ3640】JC的小苹果 概率DP+高斯消元
- 【BZOJ 3640】JC的小苹果 (高斯消元,概率DP)
- [AC自动机 概率DP 矩阵乘法||高斯消元] BZOJ 1444 [Jsoi2009]有趣的游戏
- [概率与期望 && DP] BZOJ3640 .JC的小苹果
- [高斯消元] BZOJ3640: JC的小苹果
- BZOJ 2337: [HNOI2011]XOR和路径 [高斯消元 概率DP]
- bzoj3143 [Hnoi2013]游走 (期望概率DP + 高斯消元)
- 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元
- bzoj3143: [Hnoi2013]游走【概率dp+高斯消元】
- bzoj 2337 高斯消元+概率DP
- 【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径
- bzoj 2337: [HNOI2011]XOR和路径 (概率与期望DP+高斯消元)
- 【BZOJ3270】博物馆 概率DP 高斯消元
- BZOJ_1778_[Usaco2010 Hol]Dotp 驱逐猪猡_概率DP+高斯消元
- [BZOJ2337][HNOI2011]XOR和路径(概率期望dp+高斯消元)
- 【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径
- 【BZOJ2337】XOR和路径,概率期望DP+高斯消元
- BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡 [高斯消元 概率DP]
- BZOJ 2707: [SDOI2012]走迷宫 拓扑+高斯消元+期望概率dp+Tarjan