zoukankan      html  css  js  c++  java
  • HDU4405(期望DP)

    又一道期望DP,其实这题与hdu4576那道概率DP很像(这道我也写了题解)。那么这两道一道求概率,一道求期望,又能放在一起对比一下了,期望和概率的求法的不同。

    先总结一句话:一般求概率DP或者是递推的问题,都是正着推,从初始状态往结束状态(结束状态一般是此类题要求的状态)推,所以先得到(或者说先已知)的是靠近初始状态的状态,所以想要求的当前状态是由可转移到此状态的前N可能个状态推过来的;而一般求期望DP,都是逆着推,从结束状态往初始状态(初始状态往往是此类题要求的状态)推,所以先得到(或者说先已知)的是靠近结束状态的状态,所以想要求的当前状态是由此状态对应接下来的N可能个状态推过来的。

    本题题意:数轴上有N+1个点(编号0~N),一个人玩游戏,从0出发,当到达N或大于N的点则游戏结束。每次行动掷骰子一次,骰子编号1-6,掷到多少就向前走几步,这个数轴上还有些特殊点,这些点类似飞行棋中的飞行点,只要到达这些点就可以直接飞到给定点。求总共投掷骰子次数的期望。

    例如本题,倒着过来分析。用dp[i]表示在i位置时,距离游戏结束还要投掷次数的期望。显然dp[n]为0,需要求的是dp[0]。对于直接飞过去的点。例如用数组vis[]来表示,vis[a]=b,表示当到达a点时可以直接飞到b点,那么显然dp[vis[a]]=dp[a]。倒着推,dp[i](假设该点不属于可飞行的点)的下面一个状态有6种可能(即对应6种可能的骰子数),每种都是1/6的概率。所以for(int x=1;x<=6;x++)dp[i]+=dp[i+x]/6.0;dp[i]+=1;注意最后加玩每种可能性的期望后要+1,因为这6种可能性加起来只是下一个状态的期望,当前状态是他们的前一个状态,所以期望(直接理解为投掷骰子的次数)要+1。具体代码如下:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <cstring>
    #define ll long long
    double dp[100005];
    int vis[100005];
    
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF){
            if((n+m)==0)break;
            memset(vis,-1,sizeof(vis));
            for(int i=1;i<=m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                vis[a]=b;
            }
            memset(dp,0,sizeof(dp));
            for(int i=n-1;i>=0;i--){
                if(vis[i]==-1){
                    for(int j=1;j<=6;j++){
                        dp[i]+=dp[i+j]/6.0;
                    }
                    dp[i]+=1;
                }
                else
                     dp[i]=dp[vis[i]];
            }
            printf("%.4lf
    ",dp[0]);
        }
        return 0;
    }
  • 相关阅读:
    C# 复制文件夹,移动文件夹
    让Base64适合在URL中使用
    修复FIREBIRD数据库
    Image.FromFile 锁文件的解决办法
    Powerbuilder 12.5 下载地址
    C# 给程序添加许可
    WIN FORM 多线程更新UI(界面控件)
    .Net WinForm 拖动控件
    SQL Server 自动增长清零
    C# 一次生成多个相同的字符
  • 原文地址:https://www.cnblogs.com/kevinACMer/p/3724671.html
Copyright © 2011-2022 走看看