题目:
我们正在玩一个猜数游戏,游戏规则如下:
- 我从
1****到n之间选择一个数字。 - 你来猜我选了哪个数字。
- 如果你猜到正确的数字,就会 赢得游戏 。
- 如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。
- 每当你猜了数字
x并且猜错了的时候,你需要支付金额为x的现金。如果你花光了钱,就会 输掉游戏 。
给你一个特定的数字 n ,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。
算法:
方法一:动态规划
记忆化搜索是咋回事
func getMoneyAmount(n int) int {
// dp表示取值范围位[i,j]时,猜对数字的最小代价
// dp[i][j] = k + min(dp[i][k - 1], dp[i + 1][j])
dp := make([][]int, n + 1)
for i := range dp {
dp[i] = make([]int, n + 1)
}
// i从小到大遍历的话,求dp[1][n]时,dp[n-1][n]还没有初始化,还是0
for i := n; i > 0; i -- {
for j := i + 1; j <= n; j ++ {
// 这里时k = j的情况
// dp[i][j] = max(j + dp[i][j - 1], j + dp[j + 1][j])
// = j + dp[i][j - 1]
// for循环就不用处理j = k的情况了
dp[i][j] = j + dp[i][j - 1]
for k := i; k < j; k ++ {
if i < j {
dp[i][j] = min(dp[i][j], max(k + dp[i][k - 1], k + dp[k + 1][j]))
}
}
}
}
return dp[1][n]
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}