题目链接: hdu5781
题意:
有不超过k元钱,若取钱大于剩余,atm会报错,问在不超过w次报错下,取出所有钱的最小期望。
题解:
设当前状态dp[i][j],i为最大钱数,j为剩余报错数,
若i > 0、 j > 0,
则dp[i][j] =
minik=1(i−k+1i+1∗dp[i−k][j]+ki+1∗dp[k−1][j−1]+1)
,
前一项为k不超过剩余的情况,后一项为超过,1为当前操作的一步。
i = 0时为0, j=0时为无穷大。
复杂度 O(k2w) 因为k<2000, 若采取二分,最坏步数为 log20002 , 所以w = min(w, 11), 不会超时。
#include <cstdio>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 2010;
double dp[MAXN][20];
int main(int argc, char const *argv[])
{
int k, w;
for(int i = 1; i < MAXN; i++)
dp[i][0] = INF;
for(int i = 0; i < 20; i++)
dp[0][i] = 0;
for(int i = 1; i < MAXN; i++)
for(int j = 1; j < 20; j++)
{
double t = INF;
for(int k = 1; k <= i; k++)
t = min(t, (i-k+1.0)/(i+1)*dp[i-k][j]+k/(i+1.0)*dp[k-1][j-1]+1);
dp[i][j] = t;
}
while(~scanf("%d%d", &k, &w))
printf("%.6f\n", dp[k][min(w, 11)]);
return 0;
}