HDU5781 ATM Mechine

来源:互联网 发布:yum 安装vim 编辑:程序博客网 时间:2024/06/06 08:50

转载声明:http://blog.csdn.net/kyleyoung_ymj/article/details/52097240
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5781

题意:
有个小女孩,它要去取钱,可是这个ATM机子,不能查询余额,而且这个小女孩有点智障,她只知道自己卡上的金钱上限余额为【K】,但是她不知道她的钱就究竟是【0,K】中的哪个,然后这个ATM可以取无限次,但是,一旦余额小于他存折里面的钱,就会警告她一次,一旦超过W次,这个小女孩就会被去警察局啦,所以求在不被捉走的情况下,求这个小女孩能把钱全部拿走的期望.

个人感想:
首先我一开始是写了个二分代码.
我的想法是这样的,假设我现在的钱在【0,4】范围中,可是我真正只有3块,
那么我就尝试取2块,可以取,那么我剩下的钱肯定在【0,2】范围内,
我再尝试的取1块,可以取,那么我剩下的钱肯定又在【0,1】范围内,
当我再取1块的时候,就发现被警告了,说明我剩下的钱<1,那么在3次之内我就知道我已经取完了。
大概就是这样的思路,可是我的代码最后一个和答案差0.1..,反正我测了一下和我的思路,最后还是不知道哪里出现的问题,还是看看题解了,

题解在bestcoder blog上公式有点问题的,我是参考了转载的公式的

这里写图片描述
我的想法还是和这个有点不同,
dp【i】【j】理解为:剩下的可能的钱的范围是【0,i】,我还可以被警告j次.
所以 公式[j+1]应该为[j-1]
看到公式很明显是枚举我当前为k的情况【1,k】的情况,假设我取1<=t<=k,块钱,那么这公式的表示的意思就是(真实的钱 < t)*dp[k-1][j-1]的期望+(真实的钱>=t)*dp[i-k][j]/(k+1)+1最小期望,
反正就是探测性的dp了..我是没想到了..但我感觉就是2分..可是还是差那么一点..策略还是不够厉害..最后有我想的朴素代码..不过垃圾代码别看了..

ps:总是忘记为什么+1,因为求的是次数的期望,那么对于当前dp[i][j]是通过前面状态走1步过来的,所以必须+1次
分析:dp.

AC代码:

/* Author:GavinjouElephant * Title: * Number: * main meanning: * * * *///#define OUT#include <iostream>using namespace std;#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <sstream>#include <cctype>#include <vector>#include <set>#include <cstdlib>#include <map>#include <queue>//#include<initializer_list>//#include <windows.h>//#include <fstream>//#include <conio.h>#define MaxN 0x7fffffff#define MinN -0x7fffffff#define Clear(x) memset(x,0,sizeof(x))const int INF=0x3f3f3f3f;int K,W;double dp[2020][2020];double dfs(int k,int w){    if(k==0) return 0;    if(w==0) return (double)INF;    if(dp[k][w]>0)return dp[k][w];    dp[k][w]=(double)INF;    for(int i=1;i<=k;i++)    {       dp[k][w]=min(dp[k][w],dfs(i-1,w-1)*i/(k+1)+dfs(k-i,w)*(k-i+1)/(k+1)+1);    }    return dp[k][w];}int main(){#ifdef OUT    freopen("coco.txt","r",stdin);    freopen("lala.txt","w",stdout);#endif    memset(dp,-1,sizeof(dp));    while(scanf("%d%d",&K,&W)!=EOF)    {        printf("%0.6f\n",dfs(K,min(W,15)));    }    return 0;}

朴素代码:

/* Author:GavinjouElephant * Title: * Number: * main meanning: * * * *///#define OUT#include <iostream>using namespace std;#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <sstream>#include <cctype>#include <vector>#include <set>#include <cstdlib>#include <map>#include <queue>//#include<initializer_list>//#include <windows.h>//#include <fstream>//#include <conio.h>#define MaxN 0x7fffffff#define MinN -0x7fffffff#define Clear(x) memset(x,0,sizeof(x))const int INF=0x3f3f3f3f;const int maxn=2005;int K,W;int cal(int x){    int l=0;    int r=K;    int res=0;    int warning=0;    while(l!=r)    {        if(l==0&&r==1)        {            res++;            if(x<1){warning++;}            break;        }        int mid=(l+r)/2;        if(x>=mid){ x-=mid;r=r-mid;res++;}        else        {            r=mid-1;            warning++;            res++;        }    }    if(warning>W)return 0;    return res;}int main(){#ifdef OUT    freopen("coco.txt","r",stdin);    freopen("lala.txt","w",stdout);#endif    while(scanf("%d%d",&K,&W)!=EOF)    {         double ans=0;         for(int i=0;i<=K;i++)         {            int k=cal(i);            ans+=(double)k*(1.0/(K+1));         }         printf("%f\n",ans);    }    return 0;}
0 0
原创粉丝点击