BZOJ 3270: 博物馆
Sol
期望DP+高斯消元.
根据本题题意列出期望方程
\[E(i,j)=(1-p_i)(1-p_j)E(u,v)+(1-p_i)p_jE(u,j)+p_i(1-p_j)E(i,v)+p_ip_jE(i,j),u\in Edge(i,u),v\in Edge(j,v)\]
移项得
\[(1-p_i)(1-p_j)E(u,v)+(1-p_i)p_jE(u,j)+p_i(1-p_j)E(i,v)+(p_ip_j-1)E(i,j)=0,u\in Edge(i,u),v\in Edge(j,v)\]
然后就可以高斯消元了,特殊的因为至少走一步所以关于 \(E(s,t)\) 的方程
\[(1-p_i)(1-p_j)E(u,v)+(1-p_i)p_jE(u,j)+p_i(1-p_j)E(i,v)+(p_ip_j-1)E(i,j)+1=0,u\in Edge(i,u),v\in Edge(j,v)\]
Code
/************************************************************** Problem: 3270 User: BeiYu Language: C++ Result: Accepted Time:376 ms Memory:3104 kb ****************************************************************/ #include<cstdio> #include<cmath> #include<iostream> using namespace std; #define H(i,j) (i*n+j) inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } const int N = 22; int n,m,s,t;bool b[N][N]; double p[N],a[N*N][N*N];int du[N]; void init(){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int u=0;u<n;u++) if(b[i][u]) for(int v=0;v<n;v++) if(b[j][v]&&u!=v){ int h1=H(i,j),h2=H(u,v); if(i==u&&j==v) a[h1][h2]+=p[u]*p[v]; else if(i==u) a[h1][h2]+=p[u]*(1-p[v])/du[v]; else if(j==v) a[h1][h2]+=(1-p[u])*p[v]/du[u]; else a[h1][h2]+=(1-p[u])*(1-p[v])/du[u]/du[v]; } for(int i=0;i<n*n;i++) a[i][i]-=1; } void gauss(int n){ for(int i=0,r,j,k;i<n;i++){ for(r=i,j=i+1;j<n;j++) if(fabs(a[r][i])<fabs(a[j][i])) r=j; if(r!=i) for(j=0;j<=n;j++) swap(a[r][j],a[i][j]); for(j=i+1;j<n;j++){ double bas=a[j][i]/a[i][i]; for(k=i;k<=n;k++) a[j][k]-=bas*a[i][k]; } } for(int i=n-1;~i;i--){ for(int j=i+1;j<n;j++) a[i][n]-=a[j][n]*a[i][j]; a[i][n]/=a[i][i]; } } int main(){ n=in(),m=in(),s=in()-1,t=in()-1; for(int i=1,u,v;i<=m;i++) u=in()-1,v=in()-1,b[u][v]=b[v][u]=1,du[u]++,du[v]++; for(int i=0;i<n;i++) scanf("%lf",&p[i]),b[i][i]=1; a[H(s,t)][n*n]=-1;init(); // for(int i=0;i<n*n;i++) // for(int j=0;j<=n*n;j++) // printf("%.6lf%c",a[i][j]," \n"[j==n*n]); // putchar('\n'); gauss(n*n); // for(int i=0;i<n*n;i++) // for(int j=0;j<=n*n;j++) // printf("%.6lf%c",a[i][j]," \n"[j==n*n]); // putchar('\n'); for(int i=0;i<n;i++) printf("%.6lf ",a[H(i,i)][n*n]); return 0; }