hdu 5781 ATM...(概率&&DP)

本文解析了HDU5781题目,介绍了一种利用动态规划求解的方法。通过定义状态dp[i][k]表示存款在[0,i]区间内且剩余k次警告机会时的期望值,推导出状态转移方程,并给出AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hdu 5781 传送门

题意

已知账户里最多有n元,有一个取款下限,高于可以将钱取走,低于的话会被警告一次。警告次数超过m次时,将会被当做小偷。。。
n,m≤2×1e3.

题解

比赛时,没有意识到是一道DP题,一直在二分的角度想题。还是题目理解的不够深刻。下面给个数学期望的定义吧。

数学期望(mean)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和。–出自百度百科

看了很多的博文,都只是给出了DP。看到nuonuo_orz的博客的时候,才恍然大悟。也不得不佩服作者。

dp[i][k]代表已知存款在[0,i]范围内,还有k次警告次数时的期望值。设j为下次的取款数,有两种情况:

  • 如果实际存款数低于这个j的话,问题就退化成了求dp[j-1][k-1]的值
  • 如果实际存款数高于或等于这个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。

AC代码

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#define MEM(a,x) memset(a,x,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
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);  
            }  
        }  
    }   
    int k,w;  
    while(~scanf("%d%d",&k,&w)){  
        printf("%.6f\n",dp[k][min(w,11)]);
    }  
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值