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

复习了一下高斯消元解图上期望概率,笔记的话,就直接去看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

原文地址:https://www.cnblogs.com/TSHugh/p/8781586.html

时间: 2024-12-14 02:09:14

【复习】高斯消元解图上期望概率的相关文章

uva 10828 高斯消元求数学期望

Back to Kernighan-RitchieInput: Standard Input Output: Standard Output You must have heard the name of Kernighan and Ritchie, the authors of The C Programming Language. While coding in C, we use different control statements and loops, such as, if-the

算法复习——高斯消元(ssoi)

题目: 题目描述 Tom 是个品学兼优的好学生,但由于智商问题,算术学得不是很好,尤其是在解方程这个方面.虽然他解决 2x=2 这样的方程游刃有余,但是对于下面这样的方程组就束手无策了.x+y=3x-y=1于是他要你来帮忙.给定一个线性多元一次方程组,请你求出所有未知数的解.保证在 int 范围内可以处理所有问题. 输入格式 输入文件的第一行一个数字 N(1≤N≤100),表示给定的方程组中的未知数的个数,同时也是这个方程组含有的方程个数.第 2 到 N+1 行,每行 N+1 个数.每行的前 N

【BZOJ-3143】游走 高斯消元 + 概率期望

3143: [Hnoi2013]游走 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2264  Solved: 987[Submit][Status][Discuss] Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数

[BZOJ 3143][Hnoi2013]游走(高斯消元+期望)

Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. Solution 对于点u(u≠1):到达u的概率 f[u]=∑f[v]/d[v] (Edges(u,v)) 而f[1]=∑f[v]/d[v]+1

ZOJ 2619 Generator (概率、AC自动机、高斯消元)

Generator 题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2619 题意:给定一个数N,代表可以选前N个字母.然后给定一个仅有前N个字母组成的字符串,问从空串开始构造,每次可以在已有基础上从前N个字母中挑选一个加在后面,问构造的字符串的长度期望是多少? 思路:如果给定的串长度为L,那么对于构造的串,对应的状态就是0到L之间的数.如果为L即为构造成功.记F[i] 为从i状态到达L状态期望的步数,那么对于0到L

【高斯消元】兼 【期望dp】例题

[总览] 高斯消元基本思想是将方程式的系数和常数化为矩阵,通过将矩阵通过行变换成为阶梯状(三角形),然后从小往上逐一求解. 如:$3X_1 + 2X_2 + 1X_3 = 3$ $              X_2 + 2X_3 = 1$ $2X_1 + X_3 = 0$ 化为矩阵为:--->----->-----> 然后就可以通过最后一行直接求出$X_3 = ...$,将其带回第二行,算出$X_2$,同理算出$X_1$. 代码很好理解: inline void gauss(){ int

hdu 4418 高斯消元求期望

Time travel Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1480    Accepted Submission(s): 327 Problem Description Agent K is one of the greatest agents in a secret organization called Men in B

BZOJ 3143 HNOI2013 游走 高斯消元 期望

这道题是我第一次使用高斯消元解决期望类的问题,首发A了,感觉爽爽的.... 中文题目,就不翻大意了,直接给原题: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. 输出最小的总分期望值. Solution: 这题贪心很明显

【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元

[BZOJ4820][Sdoi2017]硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了.同学们觉得要加强趣味性,所以要找一个同学扔很多很多次硬币,其他同学记录下正反面情况.用H表示正面朝上,用T表示反面朝上,扔很多次硬币后,会得到一个硬币序列.比如HTT表示第一次正面朝上,后两次反面朝上.但扔到什么时候停止呢?大家提议,选出n个同学,每个同学猜一个长度为m的序列,当某