LeetCode | 375. Guess Number Higher or Lower II 树状DP

Weare playing the Guess Game. The game is as follows:

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

Everytime you guess wrong, I'll tell you whether the number I picked is higher orlower.

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 guess5, I tell you that it's higher. You pay $5.

Second round: You guess 7, I tell you that it's higher. Youpay $7.

Third round:  You guess9, 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.

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

Credits:
Special thanks to
 @agave and @StefanPochmann for adding this problem and creating all test cases.

一开始题想的是使用分治法,但是后来一想这样肯定不对,然后又考虑到深度优先遍历,这样虽然可以得到正确的结果,但是花费的时间肯定很长,然后又考虑到线型dp, 想来想去还是得不到正确的结果,最后考虑树状dp,递推公式是

mid = (s + right) / 2;

dpLeft = dp[s][mid - 1];

dpRight = dp[mid+1][right];

min = max(dpRight,dpLeft) + mid;

dp[s][right] = min;

但是这样的话可能有一些正确结果会漏过,所以mid需要继续往右,也就是mid++,然后重新判断dpleft和dpRight,如果if (dpRight + mid< min)  min = dpRight + mid; 持续这种判断直到dpLeft >= dpRight,然后min = max(dpRight,dpLeft) + mid;  dp[s][right] = min;,这样就能得到正确的dp[s][right]

 

class Solution {

public:

  int getMoneyAmount(int n) {

      vector<vector<int>> dp(n+2,vector<int>(n+2, 0));

      int mid,right;

      for (int l = 2; l <= n; l++)

      {

            for (int s = 1; s <= n - l + 1;s++)

            {

                  int min;

                  right = s + l - 1;

                  mid = (s + right) / 2;

 

                  int dpLeft; int dpRight;

                  dpLeft = dp[s][mid - 1];

                  dpRight = dp[mid+1][right];

                  min = dpRight + mid;

 

                  while (dpLeft < dpRight) {

                       if (dpRight + mid <min)

                             min = dpRight +mid;

                       mid++;

                       dpLeft = dp[s][mid - 1];

                       dpRight = dp[mid +1][right];

                  }

                  if (dpLeft + mid < min)

                       min = dpLeft + mid;

                  dp[s][right] = min;

            }

      }

      return dp[1][n];

}

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值