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.
此题开始的时候并不会做,看了标签才知道需要使用动态规划的方法解决。动态规划的思想是,如果原问题可以分解成若干规模较小的子问题。它的一个特点是最优子结构特点,即原问题的解是由子问题的最优解组成。那么此题为什么不能用普通的递归方法来解决呢?因为子问题之间不是相互独立的。子问题之间要进行比较,找出相对来说较大的pay。这道题为什么不能像之前的Guess Number Higher or Lower那种只使用二分查找来做呢?二分查找找的是某一个值,或者给出一个target,造出最接近target值时候使用二分查找比较方便,而此题是找出过程。此题的难点在于状态方程比较难想。想法是,要求这一范围内的最小pay,就是将这一范围分成三个部分,第一个是划分点,第二是划分点的左面,第三是划分点的右面。为了避免重叠子问题,保存的是最小的pay值,代码如下:
1 public class Solution { 2 public int getMoneyAmount(int n) { 3 int[][] table = new int[n+1][n+1]; 4 return DP(table,1,n); 5 } 6 public int DP(int[][] table,int s,int e){ 7 if(s>=e) return 0; 8 if(table[s][e]!=0) return table[s][e]; 9 int res = Integer.MAX_VALUE; 10 for(int i=s;i<=e;i++){ 11 table[s][e] = i+Math.max(DP(table,s,i-1),DP(table,i+1,e)); 12 res = Math.min(res,table[s][e]); 13 } 14 table[s][e] = res; 15 return res; 16 } 17 }