• LightOJ


    概率dp+高斯消元

    https://vjudge.net/problem/LightOJ-1151

    题意:刚开始在1,要走到100,每次走的距离1-6,超过100重来,有一些点可能有传送点,可以传送到前面或后面,那么概率dp没法递推,只能高斯消元

    设期望E(x),首先100这个位置的期望E(100)=0,然后可以找出方程, 对于传送点,E(x)=E(go(x)),对于非传送点,E(x)=(E(x+1)+E(x+2)+E(x+3)+E(x+4)+E(x+5)+E(x+6)+6)/cnt(cnt是可转移的点数)

    对于大于100的E肯定是0,不用考虑进来,然后高斯消元就得到了结果

    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    
    const double g=10.0,eps=1e-8;
    const int N=100+10,maxn=100000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
    
    double a[N][N],ans[N];
    void gauss(int n)
    {
        for(int i=1;i<n;i++)
        {
            if(a[i][i]==0)
            {
                int id=0;
                for(int j=i+1;j<=n;j++)
                    if(a[j][i]!=0)
                        id=j;
                for(int j=i;j<=n+1;j++)
                    swap(a[i][j],a[id][j]);
            }
            for(int j=i+1;j<=n;j++)
            {
                double t=a[j][i]/a[i][i];
                for(int k=i;k<=n+1;k++)
                    a[j][k]-=(a[i][k]*t);
            }
        }
    //    for(int i=1;i<=n;i++)
    //    {
    //        for(int j=1;j<=n+1;j++)
    //            printf("%.12f ",a[i][j]);
    //        puts("");
    //    }
        for(int i=n;i>=1;i--)
        {
            for(int j=i+1;j<=n;j++)
                a[i][n+1]-=ans[j]*a[i][j];
            ans[i]=a[i][n+1]/a[i][i];
        }
    }
    int go[N];
    int main()
    {
        int T,cnt=0;scanf("%d",&T);
        while(T--)
        {
            int n;scanf("%d",&n);
            memset(go,0,sizeof go);
            for(int i=0;i<n;i++)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                go[a]=b;
            }
    //        puts("++");
            memset(a,0,sizeof a);
            for(int i=1;i<=93;i++)
            {
                if(go[i])
                {
                    a[i][i]=1;
                    a[i][go[i]]=-1;
                }
                else
                {
                    a[i][i]=6.0;
                    for(int j=i+1;j<=i+6;j++)a[i][j]=-1.0;
                    a[i][101]=6;
                }
            }
            for(int i=94;i<=99;i++)
            {
                if(go[i])
                {
                    a[i][i]=1;
                    a[i][go[i]]=-1;
                }
                else
                {
                    a[i][i]=1.0*(100-i);
                    for(int j=i+1;j<=100;j++)a[i][j]=-1.0;
                    a[i][101]=6;
                }
            }
            a[100][100]=1.0;
            gauss(100);
            printf("Case %d: %.12f
    ",++cnt,ans[1]);
        }
        return 0;
    }
    /***********************
    
    ***********************/
    View Code
  • 相关阅读:
    poj2240
    poj1135
    poj1062
    poj3278
    2218 补丁vs错误
    必做: 1041、1024、1077、2218、1183(较难)
    poj2828
    poj3253
    洛谷P1122 最大子树和
    1074 食物链
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/8988245.html
Copyright © 2020-2023  润新知