• ZOJ 3640 Help Me Escape:期望dp


    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3640

    题意:

      有一个吸血鬼被困住了,他要逃跑。。。

      他面前有n条路,每条路有一个困难程度c[i]。

      他的初始攻击力为f。

      每天他会从中随机选一条路:

        (1)如果当前攻击力 > c[i],那么他会再花t天走这条路成功逃跑(t的公式如图)。

          

        (2)攻击力 <= c[i],这条路他走不过去,但可以让他的攻击力 += c[i]。

      问你成功逃跑所需天数的期望。

    题解:

      表示状态:

        dp[i] = expected time(攻击力为i时,逃跑还需要的天数)

     

      找出答案:

        ans = dp[f]

        初始攻击力为f。

     

      如何转移:

        对于每一条路,每一次被选择的概率都为1/n。

        当前攻击力为i,枚举每一条路j,则:

          (1)if i > c[j]: dp[i] += t/n (可以用t天逃跑)

          (2)else: dp[i] += (dp[i+c[j]]+1)/n (攻击力增加c[j]后所用天数 + 今天一天)

      边界条件:

        对于一个攻击力max_atk满足max_atk > 所有的c[i],则所有的dp[max_atk]都相等。

        (因为只能逃跑,不能再攒攻击力了)

        所以找出满足条件的最小的max_atk,max_atk = max( max(c[i]), f )。

        可能用到的攻击力最大为max_atk*2。

        (根据Code: "else dp[i]+=(dp[i+c[j]]+1)/n")

        所以按从max_atk*2到f的顺序求dp就行了。

        初始值(设成啥都行。。。没用):set dp = 0

    AC Code:

     1 // state expression:
     2 // dp[i] = expected time
     3 // i: present atk
     4 //
     5 // find the answer:
     6 // ans = dp[f]
     7 //
     8 // transferring:
     9 // now: dp[i]
    10 // enum: c[j]
    11 // if i > c[j] dp[i] += t/n
    12 // else dp[i] += (dp[i+c[j]]+1)/n
    13 //
    14 // boundary:
    15 // set dp = 0
    16 #include <iostream>
    17 #include <stdio.h>
    18 #include <string.h>
    19 #include <math.h>
    20 #define MAX_N 105
    21 #define MAX_F 30005
    22 
    23 using namespace std;
    24 
    25 int n,f;
    26 int max_atk;
    27 int c[MAX_N];
    28 double dp[MAX_F];
    29 
    30 void read()
    31 {
    32     max_atk=f;
    33     for(int i=0;i<n;i++)
    34     {
    35         cin>>c[i];
    36         max_atk=max(max_atk,c[i]);
    37     }
    38 }
    39 
    40 void solve()
    41 {
    42     memset(dp,0,sizeof(dp));
    43     for(int i=max_atk*2+100;i>=f;i--)
    44     {
    45         for(int j=0;j<n;j++)
    46         {
    47             if(i>c[j]) dp[i]+=floor((1.0+sqrt(5))/2.0*c[j]*c[j])/n;
    48             else dp[i]+=(dp[i+c[j]]+1)/n;
    49         }
    50     }
    51 }
    52 
    53 void print()
    54 {
    55     printf("%.3f
    ",dp[f]);
    56 }
    57 
    58 int main()
    59 {
    60     while(cin>>n>>f)
    61     {
    62         read();
    63         solve();
    64         print();
    65     }
    66 }
  • 相关阅读:
    FR #3题解
    L3-005. 垃圾箱分布
    L2-004. 这是二叉搜索树吗?
    L2-002. 链表去重
    L1-009. N个数求和
    L3-003. 社交集群
    L3-004. 肿瘤诊断
    L2-001. 紧急救援
    L3-002. 堆栈
    L2-007. 家庭房产
  • 原文地址:https://www.cnblogs.com/Leohh/p/7577633.html
Copyright © 2020-2023  润新知