ZOJ3640(概率DP)

3 篇文章 0 订阅

题意

某人被抓进了洞穴,要想办法逃出来。洞穴有N个出口,每个洞口有一个怪,每个怪有战斗力C[i]。

这个人的初始战斗力是f。每天他会选择一个出口逃走。

如果他的战斗力f>C[i],那么他可以打败怪物并花费t[i] = (1.0+sqrt(5.0))*0.5*C[i]*C[i](取整)天逃出去。

否则他会修炼一天,战斗力提升f = f+c[i]。第二天再随机选择一个出口。

此人一定能逃出去,问他逃出去的天数期望

 题解

如果设DP[x]是战斗力为x逃出去的天数期望

如果当前的战斗力高于C[i]那么DP[x] += t[i]/n。

否则DP[x] += (DP[x+C[i]] + 1)/ n

那么两种方法,一种是dfs记忆化搜索,一种是递推(但是要逆向推倒)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
int c[maxn];
int t[maxn];
double dp[100000];
int n;
double dfs(int x)
{
    if(dp[x]>0) return dp[x];
    for(int i = 1; i <= n; i++)
    {
        if(x > c[i])
            dp[x]+=(double)t[i]/n;
        else
            dp[x]+=(dfs(x+c[i])+1.0)/n;
    }
    return dp[x];
}
int main()
{
    double f;
    while(~scanf("%d%lf", &n, &f))
    {
        memset(dp, 0, sizeof(dp));
        double p = (1.0+sqrt(5.0))*0.5;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &c[i]);
            t[i] = p*c[i]*c[i];
        }
        double ans = dfs(f);
        printf("%.3lf\n", ans);
    }
    return 0;
}

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
int c[maxn];
int t[maxn];
double dp[100000];
int n, f;
int main()
{

    while(~scanf("%d%d", &n, &f))
    {
        memset(dp, 0, sizeof(dp));
        double p = (1.0+sqrt(5.0))*0.5;
        int Max = -1;
        int m;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &c[i]);
            Max = max(c[i], Max);
            t[i] = p*c[i]*c[i];
            cout << i << " " << t[i] << endl;
        }
        m = 2*Max;
        if(f > Max) {
            m = f;
        }
        for (int i=m;i>=f;--i)
            for (int j=1;j<=n;++j)
                if (i>c[j]) dp[i]+=t[j]/(double)n;
                else dp[i]+=(dp[i+c[j]]+1)/(double)n;

        printf("%.3lf\n", dp[f]);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值