• zoj3640:概率(期望)dp


    题目大意:有一个吸血鬼,初始攻击力为f,每天随机走到n个洞里面,每个洞有一个c[i],如果他的攻击力f>c[i]

    则可以花费t[i] 的时间逃走,否则则花费一天时间使自己的攻击力增加c[i],求逃走天数的期望

    分析:

    这道题求期望,,考虑采用概率dp求解

    想到的最简单方法就是dp[i][j]表示 第i天,攻击力为j的概率,然后对每一个c进行转移,最后统计答案

    但是发现i,j的范围都是10000,n是100 这么做显然是行不通的

    于是又可耻的搜了一下题解,发现有一个博主写的期望dp这个概念很不错

    令 dp[a]表示 攻击力为 a 后 还需要多少天逃出的期望,那么dp[f]即为答案

    注意关键是这个 “还”

    状态转移:

    如果 a>c[i]  那么显然还需要 t[i]时间逃出

    如果 a<=c[i] 那么先要花费一天把攻击力增加a+c[i],然后还要花费的时间就是 dp[a+c[i]]

    这样转移方程就很好写了

    由于需要从后往前转移,采用记忆化搜索写

    开始数组开10010 老是segment fault 后来开到10W过了。。

    代码:

    #include <iostream>
    #include <stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #pragma comment(linker, "/STACK:102400000,102400000")
    using namespace std;
    int n,f;
    double p;
    double dp[100010];
    int c[1110];
    bool vi[100010];
    double dfs(int a)
    {
        if(vi[a])
            return dp[a];
        vi[a]=1;
        for(int i=0;i<n;i++)
        {
            if(a>c[i])
                dp[a]+=(double)floor(p*c[i]*c[i])/(double)n;
            else
                dp[a]+=(1.0+dfs(a+c[i]))/(double)n;
        }
        return dp[a];
    }
    int main()
    {
        while(scanf("%d%d",&n,&f)!=EOF)
        {
            for(int i=0;i<n;i++)
            {
                scanf("%d",c+i);
            }
            memset(dp,0,sizeof(dp));
            memset(vi,0,sizeof(vi));
            p=(1.0+sqrt(5.0))/2.0;
            printf("%.3f
    ",dfs(f));
        }
        return 0;
    }
  • 相关阅读:
    BZOJ5212 ZJOI2018历史(LCT)
    BZOJ5127 数据校验
    253. Meeting Rooms II
    311. Sparse Matrix Multiplication
    254. Factor Combinations
    250. Count Univalue Subtrees
    259. 3Sum Smaller
    156. Binary Tree Upside Down
    360. Sort Transformed Array
    348. Design Tic-Tac-Toe
  • 原文地址:https://www.cnblogs.com/oneshot/p/4013335.html
Copyright © 2020-2023  润新知