沈阳集训day6 机房模拟赛 t1自动取款机 题解

来源:互联网 发布:linux查看当前用户和组 编辑:程序博客网 时间:2024/05/20 11:47

自动取款机(256M,1s)


【问题描述】


小沈阳在小品里说过:“人生最痛苦的事情是人死了,钱还没花了”。 于是小宋(80 岁)决定要将所有的储蓄从 ATM 机中取出花光。 小宋忘记了她有多少存款 (银行卡密码她是记得的 2333),这个奇怪的 ATM 不支持查询存款余额功能。小宋知道她 存款的唯一信息是存款上限是 K 元,这意味着小宋的存款 x 是 0 到 K 之间的随机整数(包 括 K)。 每次小宋都可以尝试从 ATM 中拿出一些钱。 如果她要取的 y 元钱不大于她的存款, ATM 将立即给小宋 y 元。 但如果她的存款小于 y,小宋将收到 ATM 的警告。 如果小宋被警告超过 w 次,那么她将被警方带走,作为小偷。 小宋希望取钱次数期望最小。 由于小宋聪明,她总是采取最好的策略。 请计算小宋将所有储蓄从自动取款机中取出期望次数最小值是多少,并不得被警方带走。

【输入格式】


每个测试点包含多组测试数据(最多 10 组) 每组测试数据包含两个整数 K,和 W 1≤K,W≤2000

【输出格式】


对于每组测试数据输出取钱次数最小的期望值,舍入到小数点后 6 位。

【样例输入】


11
42
203

【样例输出】


1.000000
2.400000
4.523810


然而她并不知道赵本山说了:“人生最最痛苦的事情是人活着呢钱没了” 这是个悲伤的故事。

显然,这是一道比较入门的期望dp,基本没有任何难度(只是在嘲讽自己做不出来),我们可以这样考虑
取完不单单是指他存折里没钱了,小宋需要得到确定的信息告诉他取完了。
譬如小宋知道存折里最多1元,取一次就取完了。
或者当取1元的时候被警告了,也表示他存折里没钱了。
考虑dp[i][j]表示当前小宋直到存折里钱数上限为i,还可被警告j次,取完钱的期望。

这里写图片描述
注意到题目中有一句话非常地关键,那就是小宋非常聪明,每次总是采取最优的猜钱方式,所以如果用二分这种方法比较聪明的话,小宋一定会采取这种或者比这种方法更优的方法,所以呢,最多猜log2000次,所以直接优化即可
w=min(w,log2000)

代码如下

#include<cstdio>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;double dp[2010][16];double dfs(int w,int c){    if(dp[w][c]!=-1) return dp[w][c];    if(w==0) return 0;    if(c==0) return 1e9;    double ans=1e9;    double k=1.0/(1.0+w);    for(int i=1;i<=w;i++)    ans=min(ans,i*k*dfs(i-1,c-1)+(w+1-i)*k*dfs(w-i,c)+1);    return dp[w][c]=ans;}int main(){    int k,w;    for(register int i=0;i<=2010;i++){        for(register int j=0;j<=16;j++){            dp[i][j]=-1;        }    }    while(scanf("%d%d",&k,&w)!=EOF){        w=min(w,15);        printf("%0.6lf\n",dfs(k,w));    }    return 0;}