题意
取款机里面有0-K不确定的钱数,如果查询的钱数超过余额就会警告一次,否则不警告,求警告W次内猜到确定钱数的期望是多少。
思路
dp[i][j]表示还剩0~i的钱数时还可以被警告j次的期望。
那么得到
dp[i][j]=dp[k−1][j−1]∗ki+1+dp[i−k][j]∗i+1−ki+1+1
这样枚举的复杂度是
O(k∗w∗k)
的。然后题目说这个人很聪明,所以肯定能想到二分法,这样他最多
log2K
次就能猜出来,所以
W=min(W,log2K)
,直接取12即可。
代码
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
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;
}