【Bzoj3270】博物馆
感觉自己的概率与期望不是非常熟练,所以练习一下。
首先,这道题用二元组(x,y)表示状态,表示当前A走到x,B走到y
然后可以列出n*n个方程
高斯消元即可,时间复杂度O(n^6)
P.S. 注意几个赋值为-1的地方
1 #include<cstdio> 2 #include<vector> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=23; 7 const double eps=1e-9; 8 int n,m,u,v,s,t,d[maxn],size; 9 double p[maxn],out[maxn],b[410][410],ans[410]; 10 vector <int> a[maxn]; 11 int id(int x,int y){ 12 return n*(x-1)+y; 13 } 14 void build(int x,int y){ 15 b[id(x,y)][id(x,y)]=-1; 16 for (int i=0; i<a[x].size(); i++) 17 for (int j=0; j<a[y].size(); j++) { 18 int uu=a[x][i]; int vv=a[y][j]; 19 if (uu!=vv) { 20 if (uu==x && vv==y) b[id(x,y)][id(uu,vv)]+=p[x]*p[y]; 21 else if (uu==x && vv!=y) b[id(x,y)][id(uu,vv)]+=p[x]*out[vv]; 22 else if (uu!=x && vv==y) b[id(x,y)][id(uu,vv)]+=p[y]*out[uu]; 23 else if (uu!=x && vv!=y) b[id(x,y)][id(uu,vv)]+=out[uu]*out[vv]; 24 } 25 } 26 } 27 void gauss(){ 28 for (int i=1; i<size; i++) { 29 int num=i; 30 for (int j=i+1; j<=size; j++) if (fabs(b[j][i])>fabs(b[num][i])) num=j; 31 if (num!=i) for (int j=1; j<=size+1; j++) swap(b[num][j],b[i][j]); 32 for (int j=i+1; j<=size; j++) { 33 if (fabs(b[j][i]<eps)) continue; 34 double tt=b[j][i]/b[i][i]; 35 for (int k=1; k<=size+1; k++) b[j][k]-=tt*b[i][k]; 36 } 37 } 38 for (int i=size; i>0; i--) { 39 double tt=1.00*b[i][size+1]; 40 for (int j=i+1; j<=size; j++) tt-=1.00*ans[j]*b[i][j]; 41 ans[i]=tt/b[i][i]; 42 } 43 } 44 int main(){ 45 scanf("%d%d%d%d",&n,&m,&s,&t); 46 size=n*n; 47 b[id(s,t)][size+1]=-1; 48 for (int i=1; i<=m; i++) { 49 scanf("%d%d",&u,&v); 50 a[u].push_back(v); 51 a[v].push_back(u); 52 d[u]++; d[v]++; 53 } 54 for (int i=1; i<=n; i++) scanf("%lf",&p[i]); 55 for (int i=1; i<=n; i++) a[i].push_back(i),out[i]=(1.0-p[i])/(double)d[i]; 56 for (int i=1; i<=n; i++) 57 for (int j=1; j<=n; j++) build(i,j); 58 gauss(); 59 for (int i=1; i<=n; i++) printf("%.6lf ",fabs(ans[id(i,i)])); 60 printf("\n"); 61 return 0; 62 }