Skip to content

【动规】猜数字大小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);
    }
};