【动规】猜数字大小2
guess number 2
我们正在玩一个猜数游戏,游戏规则如下:
我从 1 到 n 之间选择一个数字。 你来猜我选了哪个数字。 如果你猜到正确的数字,就会 赢得游戏 。 如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。 每当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。如果你花光了钱,就会 输掉游戏 。 给你一个特定的数字 n ,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。
递归结构是显然的,但是递归的分割点并不能通过贪心法(左右求和之差最小)确定。于是只能遍历分割点,并且利用动规加速。
dp[i][j]
:猜数字的范围为[i, j]
时获胜所需最小金额。
class Solution {
private:
int dp[201][201];
public:
int dfs(int start, int end) {
if (dp[start][end] != 0) return dp[start][end];
if (start == end) return dp[start][end] = 0;
if (start + 1 == end) return dp[start][end] = start;
int ans = 0x7fffffff;
for (int k = end - 1; k > start; k -= 2) {
int cur = max(dfs(start, k - 1), dfs(k + 1, end)) + k;
ans = min(ans, cur);
}
return dp[start][end] = ans;
}
int getMoneyAmount(int n) {
memset(dp, 0, sizeof(dp));
return dfs(1, n);
}
};