• BZOJ 3143: [Hnoi2013]游走 [概率DP 高斯消元]


    一个无向连通图,顶点从1编号到N,边从1编号到M。 
    小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 
    现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

     

    输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。


    做过一道类似的后感觉比较简单了

    求$f[i]$到每个点的概率

    $f[i]=sumlimits_{(i,j) in E}{f[j]*frac{1}{d[j]}}$

    $f[1]$额外加上$1$

    $f[n]=0$因为到$n$后就不走了没必要用$n$的概率

    然后就可以得到通过一条边的概率啦,贪心分配即可

    然后BZOJ数据太弱了....洛谷的数据在消元时还要判断系数$<eps$

    PS:这种题应该保证有解吧

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=505;
    double eps=1e-7;
    inline int read(){
        char c=getchar();int x=0;
        while(c<'0'||c>'9'){c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x;
    }
    int n,m,u,v;
    int d[N];
    double p[N],a[N][N];
    struct edge{
        int v,ne,u;
    }e[N*N<<1];
    int h[N],cnt=0;
    inline void ins(int u,int v){
        cnt++;
        e[cnt].u=u;e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].u=v;e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    void buildEquation(){
        for(int i=1;i<n;i++){
            a[i][i]=1;int j;
            for(int k=h[i];k;k=e[k].ne) j=e[k].v,a[i][j]=-1.0/d[j];
        }
        a[1][n+1]=1;
        a[n][n]=1;a[n][n+1]=0;
    }
    void GaussElimination(){
        for(int i=1;i<=n;i++){
            int r=i;
            for(int j=i+1;j<=n;j++) if(abs(a[j][i])>abs(a[r][i])) r=j;
            if(r!=i) for(int k=1;k<=n+1;k++) swap(a[r][k],a[i][k]);
            for(int j=i+1;j<=n;j++) if(abs(a[j][i])>eps){
                double t=a[j][i]/a[i][i];
                for(int k=i;k<=n+1;k++) a[j][k]-=t*a[i][k];
            }
        }
        for(int i=n;i>=1;i--){
            for(int j=n;j>i;j--) a[i][n+1]-=a[i][j]*a[j][n+1];
            a[i][n+1]/=a[i][i];
            p[i]=a[i][n+1];
        }
    }
    double f[N*N];
    void solve(){
        for(int i=1;i<=m;i++){
            int u=e[i<<1].u,v=e[i<<1].v;
            f[i]=p[u]/d[u]+p[v]/d[v];
        }
        sort(f+1,f+1+m);
        double ans=0;
        for(int i=1;i<=m;i++) ans+=(m-i+1)*f[i];
        printf("%.3lf",ans);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();m=read();
        for(int i=1;i<=m;i++) u=read(),v=read(),ins(u,v),d[u]++,d[v]++;
        buildEquation();
        GaussElimination();
        solve();
    }
     
     
  • 相关阅读:
    js递归遍历
    .NET Core 图片操作在 Linux/Docker 下的坑
    远程桌面连接出现CredSSP的解决方法
    端口被占用解决方案
    当遇到“无法启动 IIS Express Web 服务器。”时的解决方案
    SQL Server索引设计
    python自动化之UI自动化框架搭建四--完成(关键字驱动)
    python自动化之UI自动化框架搭建三(关键字驱动)
    python自动化之UI自动化框架搭建二(关键字驱动)
    python自动化之ui自动化框架搭建一(关键字驱动)
  • 原文地址:https://www.cnblogs.com/candy99/p/6418877.html
Copyright © 2020-2023  润新知