題目
https://cn.vjudge.net/problem/HDU-5781
題意
愛麗絲將把她所有的積蓄從自動櫃員機中取出。愛麗絲忘了她有多少存款,而這個奇怪的自動取款機不支持查詢存款。愛麗絲唯一知道的關於她的存款的信息是上限K元(這意味着愛麗絲的存款x是0到K之間(包括0和K之間)的隨機整數)。
每次愛麗絲(Alice)可以嘗試從自動櫃員機(ATM)上取些錢。如果她的存款不少於y,ATM會立即給Alice y人民幣。但是,如果她的存款少於y,Alice將收到ATM的警告。
如果愛麗絲警告次數多於W次,她將被警察帶走作爲小偷。
愛麗絲希望儘可能減少操作次數。
由於愛麗絲足夠聰明,她總是採取最佳策略。
請計算愛麗絲將所有積蓄從自動取款機中取出並帶回家而不被警察帶走的期望時間。
思路
dp[i][j] 表示有(0-i)錢 可以選錯j次的最少次數
對於這個狀態我們枚舉決策(選擇取k)找最小值
轉移式
dp[i][j] = min(dp[i][j], dp[i - k][j] * (i - k + 1) / (i + 1) + dp[k - 1][j - 1] * k / (i + 1) + 1);
dp[i][j] = min(dp[i][j],取成功還剩(i-k)還可以錯j次 + 取失敗還剩(0-k-1)還可以錯(j-1) 次
代碼
#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
double dp[2010][12];
void init()
{
fill(dp[0], dp[0] + 2010 * 12, inf);
for(int i = 0; i < 12; i++)
dp[0][i] = 0;
for(int i = 1; i < 2001; i++)
for(int j = 1; j < 12; j++)
for(int k = 1; k <= i; k++)
dp[i][j] = min(dp[i][j], dp[i - k][j] * (i - k + 1) / (i + 1) + dp[k - 1][j - 1] * k / (i + 1) + 1);
}
int main()
{
int k, w;
init();
while(cin >> k >> w)
{
w = min(w, 11);
printf("%.6lf\n", dp[k][w]);
}
return 0;
}