zoukankan      html  css  js  c++  java
  • bzoj3270博物馆——期望概率DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3270

    设计一个状态表示两个人分别在两个点的状态,带个标号num[i][j];

    据此得到状态之间转移的关系所构成的n元方程,高斯消元求解;

    要注意起点的概率要+1,而且开始时两个人在两个点是有区分的,所以不能(A,B)和(B,A)都加;

    用scanf会CE,所以改成了快读和cin;

    调了一天的才找到错误竟然是把d数组和deg数组弄混了!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,m,A,B,deg[25],ct,head[25],cnt;
    double d[630],a[630][630],p[25];
    struct N{
        int to,next;
        N(int t=0,int n=0):to(t),next(n) {}
    }edge[625];
    int num(int a,int b){return n*(a-1)+b;}
    void gauss()
    {
        for(int x=1;x<=cnt;x++)
        {
            int nw=x;
            for(int y=x+1;y<=cnt;y++)
                if(fabs(a[y][x])>fabs(a[nw][x]))nw=y;
            if(nw!=x)
                for(int k=x;k<=cnt+1;k++)swap(a[nw][k],a[x][k]);
            for(int y=x+1;y<=cnt;y++)
            {
                double r=a[y][x]/a[x][x];
                for(int t=cnt+1;t>=x;t--)//
                    a[y][t]-=r*a[x][t];
            }
        }
        for(int i=cnt;i;i--)
        {
            for(int j=i+1;j<=cnt;j++)
                a[i][cnt+1]-=a[i][j]*d[j];
            d[i]=a[i][cnt+1]/a[i][i];
        }
    }
    int rd()
    {
        char ch=getchar();int x=0,f=1;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int main()
    {
    //    scanf("%d%d%d%d",&n,&m,&A,&B);
        n=rd();m=rd();A=rd();B=rd();
        for(int i=1,x,y;i<=m;i++)
        {
    //        scanf("%d%d",&x,&y);
            x=rd();y=rd();
            deg[x]++,deg[y]++;
            edge[++ct]=N(y,head[x]);head[x]=ct;
            if(x==y)continue;
            edge[++ct]=N(x,head[y]);head[y]=ct;
        }    
        for(int i=1;i<=n;i++)
    //        scanf("%lf",&p[i]);
            cin>>p[i];
        cnt=n*n;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)    if(i!=j)
            {
                int x=num(i,j);
                for(int k=head[i];k;k=edge[k].next)
                {
                    for(int l=head[j];l;l=edge[l].next)
                    {
                        a[num(edge[k].to,edge[l].to)][x]+=(1.0-p[i])*(1.0-p[j])/deg[i]/deg[j];
    //                    a[num(i,edge[l].to)][x]+=(1.0-p[j])*p[i]/d[j];//重复 
                    }
                    a[num(edge[k].to,j)][x]+=(1.0-p[i])*p[j]/deg[i];
                }
                for(int l=head[j];l;l=edge[l].next)a[num(i,edge[l].to)][x]+=(1.0-p[j])*p[i]/deg[j];
                a[x][x]+=p[i]*p[j];
            }
        for(int i=1;i<=cnt;i++)a[i][i]-=1.0;
        a[num(A,B)][cnt+1]-=1.0;
    //    printf("a[%d]=%.2lf
    ",num(A,B),a[num(A,B)][cnt+1]);
    //    a[num(B,A)][cnt+1]-=1.0;//两人有区分! 
        gauss();
        for(int i=1;i<=n;i++)
            printf("%.6lf ",d[num(i,i)]);
        return 0;
    }
  • 相关阅读:
    回家第二周
    回文
    回家第一周
    回家第四周
    《大道至简》读后感
    第三周Java课后题
    Java小测代码及截图
    【CheckBox】选择或取消所有CheckBox
    Web Developer's Handbook
    Oracle PL/SQL
  • 原文地址:https://www.cnblogs.com/Zinn/p/9069811.html
Copyright © 2011-2022 走看看