zoukankan      html  css  js  c++  java
  • 【复习】高斯消元解图上期望概率

    复习了一下高斯消元解图上期望概率,笔记的话,就直接去看SengXian的blog吧.
    BZOJ 1444 - [Jsoi2009]有趣的游戏
    https://blog.sengxian.com/solutions/bzoj-1444

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    const int N=11;
    char s[N*2];
    int n,m,l,cnt,trans[N*N][N],id[N*N],fail[N*N],pos[N],queue[N*N],front,back;
    double a[N*N][N*N],temp[N*N][N*N],pro[N];
    inline void insert(int x){
        int i,p=0;
        for(i=1;i<=l;++i){
            if(!trans[p][s[i]-'A'])trans[p][s[i]-'A']=++cnt;
            p=trans[p][s[i]-'A'];
        }
        id[p]=x,pos[x]=p;
    }
    inline void Build(){
        front=back=0;
        queue[back++]=0;
        int x,i;
        while(front!=back){
            x=queue[front++];
            for(i=0;i<m;++i)
                if(trans[x][i]){
                    queue[back++]=trans[x][i];
                    fail[trans[x][i]]=x?trans[fail[x]][i]:0;
                }else
                    trans[x][i]=x?trans[fail[x]][i]:0;
        }
    }
    inline void PF(){
        register int i,j,k;
        for(i=0;i<=cnt;++i)
            for(j=0;j<=cnt;++j)
                temp[i][j]=0;
        for(i=0;i<=cnt;++i)
            for(j=0;j<=cnt;++j)
                for(k=0;k<=cnt;++k)
                    temp[i][j]+=a[i][k]*a[k][j];
        for(i=0;i<=cnt;++i)
            for(j=0;j<=cnt;++j)
                a[i][j]=temp[i][j];
    }
    int main(){
        //freopen("rio.txt","r",stdin);
        scanf("%d%d%d",&n,&l,&m);
        int i,j,x,y;
        for(i=0;i<m;++i){
            scanf("%d%d",&x,&y);
            pro[i]=(double)x/y;
        }
        for(i=1;i<=n;++i){
            scanf("%s",s+1);
            insert(i);
        }
        Build();
        for(i=0;i<=cnt;++i)
            if(!id[i])
                for(j=0;j<m;++j)
                    a[trans[i][j]][i]+=pro[j];
            else
                a[i][i]=1;
        int T=50;
        while(T--)PF();
        for(i=1;i<=n;++i)
            printf("%.2f
    ",a[pos[i]][0]);
        return 0;
    }
    大力迭代
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    const int N=11;
    char s[N*2];
    int n,m,l,cnt,trans[N*N][N],id[N*N],fail[N*N],pos[N],queue[N*N],front,back;
    double a[N*N][N*N],pro[N],b[N*N];
    inline void insert(int x){
        int i,p=0;
        for(i=1;i<=l;++i){
            if(!trans[p][s[i]-'A'])trans[p][s[i]-'A']=++cnt;
            p=trans[p][s[i]-'A'];
        }
        id[p]=x,pos[x]=p;
    }
    inline void Build(){
        front=back=0;
        queue[back++]=0;
        int x,i;
        while(front!=back){
            x=queue[front++];
            for(i=0;i<m;++i)
                if(trans[x][i]){
                    queue[back++]=trans[x][i];
                    fail[trans[x][i]]=x?trans[fail[x]][i]:0;
                }else
                    trans[x][i]=x?trans[fail[x]][i]:0;
        }
    }
    inline void Gauss(){
        int i,j,k,index;
        double mul;
        for(i=0;i<=cnt;++i){
            index=i;
            for(j=i+1;j<=cnt;++j)
                if(std::fabs(a[j][i])>std::fabs(a[index][i]))
                    index=j;
            if(std::fabs(a[index][i])==0)continue;
            if(index!=i)
                for(j=i;j<=cnt+1;++j)
                    std::swap(a[i][j],a[index][j]);
            for(j=i+1;j<=cnt;++j){
                mul=a[j][i]/a[i][i];
                for(k=i;k<=cnt+1;++k)
                    a[j][k]-=mul*a[i][k];
            }
        }
        for(i=cnt;i>=0;--i){
            for(j=i+1;j<=cnt;++j)
                a[i][cnt+1]-=a[i][j]*b[j];
            b[i]=a[i][cnt+1]/a[i][i];
        }
    }
    int main(){
        //freopen("rio.txt","r",stdin);
        scanf("%d%d%d",&n,&l,&m);
        int i,j,x,y;
        for(i=0;i<m;++i){
            scanf("%d%d",&x,&y);
            pro[i]=y==0?0:(double)x/y;
        }
        for(i=1;i<=n;++i){
            scanf("%s",s+1);
            insert(i);
        }
        Build();
        for(i=0;i<=cnt;++i)
            if(!id[i])
                for(j=0;j<m;++j)
                    a[trans[i][j]][i]+=pro[j];
        for(i=0;i<=cnt;++i)
            a[i][i]-=1;
        a[0][cnt+1]=-1;
        Gauss();
        for(i=1;i<=n;++i)
            printf("%.2f
    ",std::fabs(b[pos[i]]));
        return 0;
    }
    高斯消元

    BZOJ 3143 - [Hnoi2013]游走
    https://blog.sengxian.com/solutions/bzoj-3143

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 510
    using namespace std;
    typedef double D;
    struct T
    {
      int to,next,w;
    }c[MAXN*MAXN];
    int head[MAXN],tot;
    int n,m;
    D a[MAXN][MAXN],f[MAXN],g[MAXN*MAXN],d=1.00;
    inline void add(int x,int y,int z)
    {
        c[++tot].to=y;
        c[tot].next=head[x];
        c[tot].w=z;
        head[x]=tot;
        c[++tot].to=x;
        c[tot].next=head[y];
        c[tot].w=z;
        head[y]=tot;
    }
    int in[MAXN];
    inline D abs(D x)
    {
        return x<0?0-x:x;
    }
    inline void swap(D &x,D &y)
    {
        D temp=x;
        x=y;
        y=temp;
    }
    inline void gas()
    {
        for(int i=1,k=1;i<=n;i++,k++)
        {
            D h=abs(a[i][k]);
            int t=i;
            for(int j=i+1;j<=n;j++)
             if(abs(a[j][k]>h))
             {
              h=abs(a[j][k]);
              t=j;
             }
            if(t!=i)
            {
                for(int j=k;j<=n+1;j++)
                 swap(a[i][j],a[t][j]);
            }
            for(int j=i+1;j<=n;j++)
            {
              D to=a[j][k]/a[i][k];
              for(int l=k;l<=n+1;l++)
                  a[j][l]-=a[i][l]*to;
            }
        }
        for(int i=n;i>0;i--)
        {
            for(int j=i+1;j<=n;j++)
              a[i][n+1]-=a[i][j]*f[j];
            f[i]=a[i][n+1]/a[i][i];
        }
    }
    inline void work()
    {
        for(int i=1;i<n;i++)
            for(int j=head[i];j;j=c[j].next)
               g[c[j].w]+=f[i]/in[i];
        sort(g+1,g+m+1);
        D ans=0;
        for(int i=1;i<=m;i++)
         ans+=(D)(m-i+1)*g[i];
        printf("%.3lf",ans);
    }
    int main()
    {
        
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y,i);
            in[x]++;
            in[y]++;
        }
        in[n]=1;
        for(int i=1;i<=n;i++)
        {
           a[i][i]=-1;
           for(int j=head[i];j;j=c[j].next)
            if(c[j].to!=n)
                 a[i][c[j].to]=(D)(d/in[c[j].to]);
           a[i][n+1]=0.00;
        }
        a[1][n+1]=-1.00;
        gas();
        work();
        return 0;
    }
    Kod

    BZOJ 3640 - JC的小苹果
    https://blog.sengxian.com/solutions/bzoj-3640

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    const int N=155;
    const int M=5010;
    const int H=10010;
    int n,m,hp,co[N];
    double a[N][N],b[N],f[H][N];
    struct B{
        double x[N];
        inline friend B operator -(B w,B q){
            int i;
            for(i=1;i<=n;++i)
                w.x[i]-=q.x[i];
            return w;
        }
        inline friend B operator *(B w,double q){
            int i;
            for(i=1;i<=n;++i)
                w.x[i]*=q;
            return w;
        }
        inline double get(){
            double ret=0;
            int i;
            for(i=1;i<=n;++i)
                ret+=x[i]*b[i];
            return ret;
        }
    }bi[N];
    struct V{
        int to,next;
    }c[M<<1];
    int head[N],t;
    int degree[N];
    inline void add(int x,int y){
        c[++t].to=y,c[t].next=head[x],head[x]=t;
    }
    inline void Gauss(){
        int i,j,k,idx;
        double mul;
        for(i=1;i<=n;++i){
            idx=i;
            for(j=i+1;j<=n;++j)
                if(std::fabs(a[j][i])>std::fabs(a[idx][i]))
                    idx=j;
            if(idx!=i){
                for(j=i;j<=n;++j)
                    std::swap(a[i][j],a[idx][j]);
                std::swap(bi[i],bi[idx]);
            }
            for(j=1;j<=n;++j){
                if(i==j)continue;
                mul=a[j][i]/a[i][i];
                for(k=i;k<=n;++k)
                    a[j][k]-=a[i][k]*mul;
                bi[j]=bi[j]-bi[i]*mul;
            }
        }
    }
    inline void Gauss(double *e){
        int i,j;
        double sum;
        for(i=n;i>0;--i)
            e[i]=bi[i].get()/a[i][i];
    }
    inline void Init(){
        scanf("%d%d%d",&n,&m,&hp);
        int i,j,x,y;
        for(i=1;i<=n;++i)
            scanf("%d",&co[i]);
        for(i=1;i<=m;++i){
            scanf("%d%d",&x,&y);
            if(x==y){
                add(x,y);
                ++degree[x];
                continue;
            }
            add(x,y),add(y,x);
            ++degree[x],++degree[y];
        }
        for(i=1;i<=n;++i){
            bi[i].x[i]=1;
            if(co[i])a[i][i]=1;
            else{
                a[i][i]=-1;
                for(j=head[i];j;j=c[j].next)
                    if(c[j].to!=n)
                        a[i][c[j].to]+=1./degree[c[j].to];
            }
        }
        Gauss();
    }
    inline void Work(){
        int i,j,k;
        for(i=hp;i>0;--i){
            for(j=1;j<=n;++j){
                b[j]=0;
                if(j==1&&i==hp)
                    b[j]=-1;
                else if(!co[j])
                    b[j]=0;
                else if(i+co[j]<=hp)
                    for(k=head[j];k;k=c[k].next)
                        if(c[k].to!=n)
                            b[j]+=f[i+co[j]][c[k].to]/degree[c[k].to];
            }
            Gauss(f[i]);
        }
    }
    inline void Print(){
        double ans=0;
        int i;
        for(i=1;i<=hp;++i)
            ans+=f[i][n];
        printf("%.8lf
    ",ans);
    }
    int main(){
        //freopen("rio.txt","r",stdin);
        Init();
        Work();
        Print();
        return 0;
    }
    Kod
  • 相关阅读:
    HTTP Digest authentication
    HDU 1520 Anniversary party 树形DP
    Servlet过滤器
    Js apply 方法 具体解释
    java 读取固定目录下的文件(和上篇差点儿相同)
    使用nodeitk进行角点检測
    ~/.local/share/Trash/files
    mv,Directory not empty不能目录覆盖
    cp 提示 overwrite 问题
    cv:显示Linux命令运行进度
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8781586.html
Copyright © 2011-2022 走看看