375. Guess Number Higher or Lower II
2017-04-23 17:34
253 查看
一、题目大意
我们在玩一个猜数字的游戏,游戏规则如下:我从1到n选择一个数字,你来猜我选择的数字。
每次你猜错,我都会告诉真实值是偏大还是偏小。
然而,当你猜了一个数字x,并且猜错的时候,你必须支付$x给我,当你猜到我选择的数字时,你就可以赢得比赛。
例如:
n=10,我选择了8
第一轮:你猜5,我告诉你真实值大于该值,你支付$5;
第二轮:你猜7,我告诉你真实值大于该值,你支付$7;
第三轮:你猜9,我告诉你真实值小于该值,你支付$9;
游戏结束,我选择的数字是8 。
你最终支付了$5+$7+$9=$21。
给定一个值n≥1,求为了保证赢得比赛,你必须有多少钱。
二、编程思路
2.1、2.2节为不成功的编程思路,关心答案的同学可以直接转到2.3即可。2.1 初刻拍案惊奇
乍一看此题可以使用二分法求解。n=1,{1},ans=0;
n=2,{1,2},ans=1;
n=3,{1,2,3},ans=2;
n=4,{1,2,3,4},ans=min{2+3,3+1}=4;
…
似乎没问题,令f(x,y)表示猜[x,y]范围内所需要花的钱,med=x+y2,若med为整数,则先猜med;若med不是整数,则猜medf=floor(med)与medc=ceil(med)两种情况,取其中情况较小的。
总结其递推公式如下:
f(x,y)=0;
f(x,y)=x, y=x+1;
f(x,y)=med+f(x,med−1)+f(med+1,y), medc==medf
f(x,y)=min{medc+f(x,medc−1)+f(medc+1,y),medf+f(x,medf−1)+f(medf+1,y)}, medc!=medf
但是当n==5时,根据二分法求出来的是:n=5,{1,2,3,4,5},f(1,5)=3+4=7,而正确的结果应该是f(1,5)=2+4=6。
二分法宣告失败,这是因为二分法只能够找到猜的次数最少的,而不能够保证所猜的数字和最小。
2.2 二刻拍案惊奇
既然二分法不行,那就使用动态规划思路进行求解,继续找规律。n=1,{1},ans=0;
n=2,{1,2},ans=min{1,2}=1;
n=3,{1,2,3},ans=min{1+2,2,3+1};枚举第一次分别猜1 2 3的情况。
n=4,{1,2,3,4},ans=min{1+{2,3,4}, 2+{3,4}+{1},3+{1,2}+{4}, 4+{1,2,3}}=4;
…
n,{1,2,3,…,n},ans=MINi=ni=1{i+max({1,2,3,…,i−1}, {i+1,…,n}},即分别枚举猜1…n的情况,从而将问题分解为左右两个子序列的问题。即上式中的{1,2,3,…,i−1}与{i+1,…,n},然后分别求其需要的钱数即可。
至此,思路还没有出现问题。
经过初步观察似乎可以发现,右边序列需要的钱数{i+1,…,n}?=(似乎等于)i+{1,…,n−i}于是总结出如下递推公式:
令dp[i]表示数字范围为1…i之间时,为了保证猜中数字所需要的最少钱数,则
dp[0]=0;
dp[1]=0;
dp[2]=1;
dp[i]=MINk=ik=1(k+max{dp[k−1],dp[i−j]+((i−j)<2?0:j)})
2.3 三刻拍案惊奇
以上思路中,右边序列需要的钱数{i+1,…,n}?=(似乎等于)i+{1,…,n−i}属于根据直觉得出,与正确结果对比发现,当n≥12时,会出现错误。其实只有当子序列中只猜一次时,以上关系才成立。继续使用动态规划思路,令dp[i][j]猜中[i,j]范围之内数字时所需要最少钱数。则递推公式很容易获得,
dp[i][j]=MINk=jk=i{k+max{dp[i][k−1],dp[k+1][j]}}
三、代码设计
class Solution { public: int getMoneyAmount(int n) { if(n ==0) return 0; vector<vector<int> > dp(n+1, vector<int>(n+1, 0)); //注意此处的迭代方向 for(int i = n-1; i > 0; i--) { for(int j = i+1; j <=n; j++) { int ans = 0xfffffff; for(int k = i; k <j; k++) ans = min(ans, k + max(dp[i][k-1], dp[k+1][j])); dp[i][j] = ans; } } return dp[1] ; } };
参考博客
LeetCode题解[LeetCode]Guess Number Higher or Lower II
相关文章推荐
- 374,375. Guess Number Higher or Lower I,II
- LeetCode 375. Guess Number Higher or Lower II
- [leetcode-375]Guess Number Higher or Lower II(java)
- LeetCode | 375. Guess Number Higher or Lower II 树状DP
- LeetCode - 375 - Guess Number Higher or Lower II
- 375. Guess Number Higher or Lower II
- Leetcode:375. Guess Number Higher or Lower II
- leetcode 375. Guess Number Higher or Lower II 猜数游戏+动态规划DP+最大最小化问题
- 375. Guess Number Higher or Lower II
- Leetcode 375. Guess Number Higher or Lower II
- leetcode 375. Guess Number Higher or Lower II
- [leetcode] 375. Guess Number Higher or Lower II 解题报告
- LeetCode 375. Guess Number Higher or Lower II
- 375. Guess Number Higher or Lower II
- 375. Guess Number Higher or Lower II
- 【LEETCODE】375- Guess Number Higher or Lower II [Python]
- Leetcode 375. Guess Number Higher or Lower II (Medium) (cpp)
- LeetCode 375. Guess Number Higher or Lower II
- 375. Guess Number Higher or Lower II**
- 375. Guess Number Higher or Lower II