【复习】高斯消元解图上期望概率

复习了一下高斯消元解图上期望概率,笔记的话,就直接去看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\n",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\n",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\n",ans);
}
int main(){
    //freopen("rio.txt","r",stdin);
    Init();
    Work();
    Print();
    return 0;
}
Kod

 

posted @ 2018-04-10 18:56  TS_Hugh  阅读(...)  评论(... 编辑 收藏