HDU 5781 ATM Mechine 16多校5 概率dp


题意:Alice想把自己的存款全部取出,但是她忘记了自己的具体存款,只记得自己的存款是在[0,K]范围内的整数,同时ATM机出了毛病,不会显示存款数。当你想从里面取出不超过你存款的钱数时,它会出钞,如果想取的钱大于存款数的话,它不会出钞,还会警告你一次,当你的警告次数超过了W次时,警察会把你带走。问Alice取出所有存款且不会被警察带走的期望数。(1<=K,W<=2000)

思路:
dp[i][k]代表已知存款在[0,i]范围内,还有k次警告次数时的期望值。设j为下次的取款数,有两种情况:
  1. 如果实际存款数低于这个j的话,问题就退化成了求dp[j-1][k-1]的值
  2. 如果实际存款数高于或等于这个j的话,问题就退化成了求dp[i-j][k]的值(此时把范围确定到了[j,i],等价于把范围确定到了[0,i-j])
求期望,就是要先求所有可能情况,然后取平均不是吗?存款范围在[0,i]的话,那么存款可以是[0,i]内的任意一个数,当存款是[0,j]时,期望就取决于dp[j-1][k-1],当存款是[j+1,i]的时候,期望就取决于dp[i-j][k],因此状态转移方程是:dp[i][k]=min(dp[i][k],(j*dp[j-1][k-1]+(i-j+1)*dp[i-j][k])/(i+1)+1)。
考虑到K最大只有2000,不计警告次数的话,采用二分策略,也只要11次二分就ok。所以W超过11后,对答案就不会有影响。

边界情况:当存款范围是[0,0]的时候,不管警告次数,答案都是0。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define MS(x,y) memset(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define lowbit(x) (x&(-x))
typedef long long LL;
inline void fre1(){freopen("input.txt","r",stdin);/*freopen("output.txt","w",stdout);*/}
inline void fre2(){fclose(stdin);/*fclose(stdout);*/}
const int MAXN=2000+5;
const double EPS=1e-8;
double dp[MAXN][16];
bool vis[MAXN][16];

int main()
{
    for(int i=0;i<MAXN;++i){
        for(int j=0;j<16;++j)
            dp[i][j]=1e12;
    }
    for(int i=0;i<16;++i) dp[0][i]=0;
    for(int i=1;i<=2000;++i){
        for(int j=1;j<=i;++j){
            for(int k=1;k<=15;++k){
                dp[i][k]=min(dp[i][k],(j*dp[j-1][k-1]+(i-j+1)*dp[i-j][k])/(i+1)+1);
            }
        }
    }
//    for(int i=0;i<15;++i){
//        for(int j=0;j<15;++j){
//            printf("%12.6f",dp[i][j]);
//        }
//        putchar(10);
//    }
    int k,w;
    while(~scanf("%d%d",&k,&w)){
        printf("%.6f\n",dp[k][min(w,11)]);
    }
    return 0;
}

其它:
因为多校二的时候做了一道叫Permutation Bo的题,自己就以为求概率这种东西只要找到策略,确定不同情况对答案的贡献,就可以出解了。果然自己还是too young too navie,不过遇到了这种题,也是学习了。
题目里用dp[i]表示存款在[0,i]范围内的情况,其实就是表示[k,i+k](k为任意自然数)的情况,这种表示方法利用了题目的特殊性,节省了空间,提高了效率。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值