HDU 5781 ATM Mechine 期望dp
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5781
ATM Mechine
Memory Limit: 65536/65536 K (Java/Others)
题解:
dp[i][j]表示还剩0到i元,还可以被警告j次的最优期望步数。
代码
#include<map>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define M (l+(r-l)/2)
#define bug(a) cout<<#a<<" = "<<a<<endl;
using namespace std;
typedef __int64 LL;
const int maxn = 2222;
int n, m;
double dp[maxn][22];
int main() {
memset(dp, 0x7f, sizeof(dp));
printf("%lf\n",dp[0][0]);
memset(dp[0], 0, sizeof(dp[0]));
for (int i = 1; i < maxn; i++) {
for (int j = 1; j < 17; j++) {
//k表示的是取走k个的情况。
//如果剩余的钱数<k,那么你就会用掉一次警告并且你能知道剩余的钱数<k。
//如果剩余的钱数>=k,那么你就不会被警告,并且剩余的钱数<i-k。
for (int k = 1; k <= i; k++) {
//这边的min体现了选择的是最优策略
dp[i][j] = min(dp[i][j], k*1.0 / (i + 1)*dp[k - 1][j - 1] + (i - k + 1)*1.0 / (i + 1)*dp[i - k][j] + 1);
}
}
}
while (scanf("%d%d", &n, &m) == 2 && n) {
//m>=15次的时候二分策略就一定能定位了。
m = min(15, m);
printf("%.6lf\n", dp[n][m]);
}
return 0;
}