HDU 5781 ATM Mechine

题意

取款机里面有0-K不确定的钱数,如果查询的钱数超过余额就会警告一次,否则不警告,求警告W次内猜到确定钱数的期望是多少。

思路

dp[i][j]表示还剩0~i的钱数时还可以被警告j次的期望。
那么得到
dp[i][j]=dp[k1][j1]ki+1+dp[ik][j]i+1ki+1+1
这样枚举的复杂度是 O(kwk) 的。然后题目说这个人很聪明,所以肯定能想到二分法,这样他最多 log2K 次就能猜出来,所以 W=min(W,log2K) ,直接取12即可。

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 1e6 + 10;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;

int w, k;
double dp[2020][15];

int main()
{
    //freopen("H:\\in.txt","r",stdin);
    //freopen("H:\\out.txt","w",stdout);
    for (int i = 0; i <= 2000; i++)
        for (int j = 0; j <= 12; j++)
            dp[i][j] = INF;
    for (int i = 0; i <= 12; i++)
        dp[0][i] = 0;
    for (int i = 1; i <= 2000; i++)
        for (int j = 1; j <= 12; j++)
            for (int kk = 1; kk <= 2000; kk++)
                if (i >= kk) {
                    dp[i][j] = min(dp[i][j], (dp[kk-1][j-1] * kk * 1.0 / (i + 1) + dp[i-kk][j] * (i + 1 - kk) * 1.0 / (i + 1)) + 1);
                }
    while (scanf("%d%d", &k, &w) != EOF)
    {
        w = min(w, 12);
        printf("%.6f\n", dp[k][w]);
    }
    return 0;
}

你可能感兴趣的:(HDOJ,概率DP)