zoukankan      html  css  js  c++  java
  • HDU 4089 Activation

    概率,$dp$。

    设$dp[i][j]$表示有$i$个人在排队,$Tomato$排在第$j$个的情况下,到达目标状态的概率。$dp[n][m]$为答案。

    当$j=1$时,$dp[i][1]=p1*dp[i][1]+p2*dp[i][i]+p4$;

    当$2<=j<=k$时,$dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1]+p4$;

    当$k<j<=i$时,$dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1]$。

    将上面三个式子第一项往左移,左右同除以左边系数之后,得到:

    当$j=1$时,$dp[i][1]=A*dp[i][i]+C$;

    当$2<=j<=k$时,$dp[i][j]=A*dp[i][j-1]+B*dp[i-1][j-1]+C$;

    当$k<j<=i$时,$dp[i][j]=A*dp[i][j-1]+B*dp[i-1][j-1]$。

    其中$A=p2/(1-p1)$,$B=p3/(1-p1)$,$C=p4/(1-p1)$。

    加下来就是要把这个东西算出来。又是一顿骚操作。

    再写的简单一点吧:

    当$j=1$时,$dp[i][1]=A*dp[i][i]+x[j]$,此时$x[j]=C$;

    当$2<=j<=k$时,$dp[i][j]=A*dp[i][j-1]+x[j]$,此时$x[j]=B*dp[i-1][j-1]+C$;

    当$k<j<=i$时,$dp[i][j]=A*dp[i][j-1]+x[j]$,此时$x[j]=B*dp[i-1][j-1]$;

    $x[j]$可以通过$dp[i-1][....]$直接算出来。

    假设现在我们需要计算$dp[4][1]$至$dp[4][4]$,我们分别设$dp[4][1]$至$dp[4][4]$为$a$,$b$,$c$,$d$。

    得到四个等式:

    $a=A*d+x[1]$ ①

    $b=A*a+x[2]$ ②

    $c=A*b+x[3]$ ③

    $d=A*c+x[4]$ ④

    将②代入③,再将新得到的③代入④,再将新得到的④代入①,

    得到:$a=A^4*a+A^3*x[2]+A^2*x[3]+A^1*x[4]+A^0*x[1]$ ⑤,就可以求出$a$了,即求出了$dp[4][1]$。

    ⑤式子的得到是有规律的,自己写一遍就知道了。得到了$dp[4][1]$就可以知道$dp[4][2..4]$了。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-6;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c = getchar();
        x = 0;
        while(!isdigit(c)) c = getchar();
        while(isdigit(c))
        {
            x = x * 10 + c - '0';
            c = getchar();
        }
    }
    
    int n,m,k;
    double p1,p2,p3,p4,A,B,C;
    double dp[2][2005],x[2005];
    double powA[2005];
    
    int main()
    {
        while(~scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4))
        {
            if(p4<eps)
            {
                printf("0.00000
    ");
                continue;
            }
            A=p2/(1-p1); B=p3/(1-p1); C=p4/(1-p1);
    
            powA[0]=1; for(int i=1;i<=n;i++) powA[i]=powA[i-1]*A;
    
            int flag=0; dp[flag][1]=C/(1-A); flag=1;
            for(int i=2;i<=n;i++)
            {
                for(int j=1;j<=i;j++)
                {
                    if(j==1) x[j]=C;
                    else if(j>=2&&j<=k) x[j]=B*dp[flag^1][j-1]+C;
                    else x[j]=B*dp[flag^1][j-1];
                }
    
                double sum=0;
                for(int j=2;j<=i;j++) sum=sum+x[j]*powA[i+1-j];
                sum=sum+x[1]*powA[0];
    
                dp[flag][1]=sum/(1-powA[i]);
    
                for(int j=2;j<=i;j++)  dp[flag][j]=A*dp[flag][j-1]+x[j];
    
                flag=flag^1;
    
            }
            printf("%.5f
    ",dp[flag^1][m]);
        }
        return 0;
    }
  • 相关阅读:
    Shell 学习笔记之函数
    Shell 学习笔记之条件语句
    Shell 学习笔记之运算符
    Shell 学习笔记之变量
    [LeetCode] Zuma Game 题解
    [LeetCode] Decode String 题解
    [LeetCode] Pacific Atlantic Water Flow 题解
    TCP的建立和终止 图解
    [LeetCode] 01 Matrix 题解
    java中protect属性用法总结
  • 原文地址:https://www.cnblogs.com/zufezzt/p/6307175.html
Copyright © 2011-2022 走看看