CF113D Museum

题解:

不错的期望题

要求的是概率,但是两个人在同一房间相遇后不再移动了

所以我们希望利用这个特殊的性质将概率问题转化为期望问题,那么就是设$dp[i][j]$表示Petya在i房间Vasya在j房间这种状态的期望出现次数

由于$dp[x][x]$这样的情况最多出现1次,所以此时概率=期望

考虑转移

由于n只有22,所以我们先乱搞一个转移方程

 设$p[i][j]$表示i到j的概率

那么$dp[i][j]=\sum\limits_{a=1}^{n} \sum\limits_{b=1}^{n} p[a][i]*p[b][j]*dp[a][b]$

这样我们就得到了$n^2$有$n^2$个未知数的方程

高斯消元一下,时间复杂度是$O(n^{2*3})$

注意:由于两个人开始时刻处在状态dp[s][t],所以此时dp[s][t]=1

所以$dp[s][t]=(\sum\limits_{a=1}^{n} \sum\limits_{b=1}^{n} p[a][s]*p[b][t]*dp[a][b])+1$

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long
#define rint register int
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dgx cerr<<"=============="<<endl
#define lowbit(x) (x&(-x))
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while('0'>ch || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while('0'<=ch && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
int n,m,f,s,b[25][25],id[25][25],cnt;
double dp[1005][10][10],p[26][26],de[23],a[25],ans[26],c[625][625]; 
double ffabs(double x){
    if(x<0) return x*-1.000000;
    else return x;
}
int main(){
    cin>>n>>m>>f>>s;
    dp[0][f][s]=1;
    rep(i,1,n) rep(j,1,n) id[i][j]=++cnt;
    rep(i,1,m){
        int x,y; cin>>x>>y;
        b[x][y]++; b[y][x]++; de[x]++; de[y]++;
    }
    rep(i,1,n) cin>>a[i];
    rep(i,1,n){
        rep(j,1,n){
            if(i==j) p[i][j]=a[i];
            else if(b[i][j])p[i][j]=(1-a[i])/de[i];
        }
    }
    rep(i,1,n){
        rep(j,1,n){
            if(i==f && j==s) c[id[i][j]][cnt+1]=-1;
            c[id[i][j]][id[i][j]]=-1;
            rep(k,1,n){
                rep(l,1,n){
                    if(k==l) continue;
                    c[id[i][j]][id[k][l]]+=p[k][i]*p[l][j];
                }
            }
        }
    }
    
    rep(i,1,cnt){
        int pos=i;
        rep(j,i+1,cnt){
            if(ffabs(c[j][i])>ffabs(c[pos][i])) pos=j;
        }
        rep(j,1,cnt+1) swap(c[pos][j],c[i][j]);
        /*rep(ii,1,cnt){
            rep(jj,1,cnt+1) cout<<c[ii][jj]<<" ";cout<<endl;
        }*/
        if(!c[i][i]) return 0;
        rep(j,i+1,cnt+1) c[i][j]/=c[i][i];
        rep(k,1,cnt) rep(j,1,cnt+1) if(j!=i && k!=i) c[k][j]=c[k][j]-(c[k][i]*c[i][j]);
    }
    rep(i,1,cnt){
        if(i%n==int(i/n)+1) ans[i%n]=c[i][cnt+1];
    }
    ans[n]=c[cnt][cnt+1];
    rep(i,1,n) printf("%.8lf\n",ans[i]);
    return 0;
}

 

posted @ 2021-01-08 17:44  niolle  阅读(93)  评论(0编辑  收藏  举报