375. Guess Number Higher or Lower II

15 篇文章 0 订阅

We are playing the Guess Game. The game is as follows:

I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I'll tell you whether the number I picked is higher or lower.

However, when you guess a particular number x, and you guess wrong, you pay $x. You win the game when you guess the number I picked.

Example:

n = 10, I pick 8.

First round:  You guess 5, I tell you that it's higher. You pay $5.
Second round: You guess 7, I tell you that it's higher. You pay $7.
Third round:  You guess 9, I tell you that it's lower. You pay $9.

Game over. 8 is the number I picked.

You end up paying $5 + $7 + $9 = $21.

Given a particular n ≥ 1, find out how much money you need to have to guarantee a win.

【问题分析】

 1、该问题的意思是给定一个数字n,从1到n中取一个数字,让另外一个人猜结果

        如果对方猜错,我会告诉对方实际数字比他猜的更大,还是更小

        同时本次猜错的代价为猜错的这个数字

        求解:为了确保肯定能才对,需要付出的最小代价


2、 注意到这里的最小代价有一个前提,就是一定能猜对

       这是问题可以采用动态规划求解,现给出dp[i][j]定义,然后介绍

       dp[i][j]表示在i和j之间猜测时肯定能赢的最小代价


       从1到n中猜测可以分为两部分,如果猜测结果为k,也就是k确定了,那么猜错的代价为:

       情况1:如果真实值大于猜测值,代价为k加上k+1到n猜测的代价,因为下一步是要在k+1到n之间猜测

       情况2:如果真实值小于猜测值,代价为k加上1到k-1猜测的代价,因为下一步是要在1到k-1之间猜测

       想要肯定能猜对,那么必须从情况1和情况2中选择猜测代价最大的一种情况

       cost_k = k + max(dp[i][k-1], dp[k+1][j])

      

       当在i和j之间猜测时,也就是i和j确定了,k有多种可能

       上面说从情况1和情况2中选择猜测代价最大的情况,就是在k给定的情况下,选择猜测代价最大的情况,

       现在k变化时,不同的k有不同的最大代价,为了尽可能少付出代价,需要选择所有k情况下,代价最小的结果

       作为i到j之间猜测的肯定能赢的最小代价

       cost_i_j =min(cost_k),  i < k < j

       因此dp[1][n]即为1到n之间猜测时,肯定能赢的最小代价


【AC代码】

class Solution {
    public:
        int getMoneyAmount(int n) {
            std::vector<std::vector<int> > dp(n+2, std::vector<int>(n+2, 0));

            for (int right = 1; right <= n; ++right) {
                for (int left = right-1; left >= 1; --left) {
                    int min_val = INT_MAX;
                    for ( int mid = left; mid <= right; ++mid) {
                        int tmp = mid + std::max(dp[left][mid-1], dp[mid+1][right]);
                        min_val = std::min(min_val, tmp);
                    }
                    dp[left][right] = min_val;
                }
            }
            return dp[1][n];
        }
};


参考资料:

https://discuss.leetcode.com/topic/51370/c-more-simple-dp-solution/2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值