BZOJ 3270 博物馆 && CodeForces 113D. Museum 期望概率dp 高斯消元
大前提,把两个点的组合看成一种状态 x
两种思路 O(n^7) f[x]表示在某一个点的前提下,这个状态经过那个点的概率,用相邻的点转移状态,高斯一波就好了
O(n^6) 想象成臭气弹,这个和那个的区别只是状态维数变化,f[x]表示这个状态出现的概率,高斯一下就好了
我比较傻只想出来O(n^7)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef double D; D a[400][400],source[400][400],ans[50],keep[50],get[500],sz; int via[50][50],need,map[400000]; int n,m,Petya,Vasya; inline int hash(int x,int y) { if(x>y)x^=y^=x^=y; int gg=x*100+y; if(map[gg]==0)map[gg]=++sz; return map[gg]; } inline D abs(D x) { return x<0.0?0.0-x:x; } void gause() { for(int i=1,k=1;i<=need&&k<=need;i++,k++) { int temp=i; D h=abs(a[i][k]); for(int j=i+1;j<=need;j++) if(h<abs(a[j][k])) { temp=j; h=abs(a[j][k]); } if(temp!=i) { for(int j=k;j<=need+1;j++) swap(a[i][j],a[temp][j]); } for(int j=i+1;j<=need;j++) { h=a[j][k]/a[i][k]; for(int l=k;l<=need+1;l++) a[j][l]-=h*a[i][l]; } } for(int i=need;i>0;i--) { for(int j=i+1;j<=need;j++) a[i][need+1]-=a[i][j]*get[j]; get[i]=a[i][need+1]/a[i][i]; } } void blabla(int x) { for(int i=0;i<400;i++) for(int j=0;j<400;j++) a[i][j]=source[i][j]; a[hash(x,x)][need+1]=1.0; gause(); ans[x]=get[hash(Petya,Vasya)]; } void pre() { scanf("%d%d%d%d",&n,&m,&Petya,&Vasya); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); via[x][++via[x][0]]=y; via[y][++via[y][0]]=x; } need=n*(n+1)/2; for(int i=1;i<=n;i++) scanf("%lf",&keep[i]); for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) { int x=hash(i,j); if(i==j) { source[x][x]=1.0; continue; } D Viai=1.0*via[i][0],Viaj=1.0*via[j][0]; D Keep=(1.0-keep[i])*(1.0-keep[j])/Viai/Viaj; for(int z=1;z<=via[i][0];z++) for(int y=1;y<=via[j][0];y++) source[x][hash(via[i][z],via[j][y])]+=Keep; Keep=(1.0-keep[i])*keep[j]/Viai; for(int z=1;z<=via[i][0];z++) source[x][hash(via[i][z],j)]+=Keep; Keep=(1.0-keep[j])*keep[i]/Viaj; for(int y=1;y<=via[j][0];y++) source[x][hash(via[j][y],i)]+=Keep; source[x][x]+=keep[i]*keep[j]; source[x][x]-=1.0; } } void work() { ans[n]=1.0; for(int i=1;i<n;i++) { blabla(i); ans[n]-=ans[i]; } } void print() { for(int i=1;i<=n;i++) printf("%.10lf ",ans[i]); } int main() { pre(); work(); print(); }
苟利国家生死以, 岂因祸福避趋之。