(力扣—动态规划)石子游戏
描述
亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] 。
游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。
亚历克斯和李轮流进行,亚历克斯先开始。 每回合,玩家从行的开始或结束处取走整堆石头。 这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。
假设亚历克斯和李都发挥出最佳水平,当亚历克斯赢得比赛时返回 true ,当李赢得比赛时返回 false 。
示例:
输入:[5,3,4,5]
输出:true
解释:
亚历克斯先开始,只能拿前 5 颗或后 5 颗石子 。
假设他取了前 5 颗,这一行就变成了 [3,4,5] 。
如果李拿走前 3 颗,那么剩下的是 [4,5],亚历克斯拿走后 5 颗赢得 10 分。
如果李拿走后 5 颗,那么剩下的是 [3,4],亚历克斯拿走后 4 颗赢得 9 分。
这表明,取前 5 颗石子对亚历克斯来说是一个胜利的举动,所以我们返回 true 。
提示:
2 <= piles.length <= 500
piles.length 是偶数。
1 <= piles[i] <= 500
sum(piles) 是奇数。
思想1
直接return true
两个人都发挥最好 还是偶数堆 那第一个人必定有优势
思想2
如果直接return true那可能就有点投机取巧了
毕竟还是要做一下的
在动态规划中 碰到有关两者求最大最小的其实有一种常用的做法就是,不分别求出来 而是求差,然后最后一项是正的或负的分别代表不同结果
在我之前的博客中说过 算法是服务于解决问题的,不要纠结于怎么用某类算法去解决某个问题,也就是说 不要套模板
这道题要想保存差的话显然要用到一个二维数组
值得提前说一下的是 i - j为奇数的时候为亚历克斯选择,反之为李选择
亚历克斯的目的就是要从李的运算中加上相应堆取最大
李的目的就是要从压力克斯的运算中减去相应堆取最小
这就是对应的dp思想
python code
class Solution:
def stoneGame(self, piles: List[int]) -> bool:
dp = [[0 for i in piles] for i in piles] # 初始化dp数组
def cal(i: int, j: int):
'i代表左边界 j代表右边界'
if dp[i][j]:
return dp[i][j]
elif i + 1 == j:
return max(piles[i], piles[j])
else:
if (j - i) % 2: # 轮到压力克斯选
dp[i][j] = max(cal(i + 1, j) + piles[i], cal(i, j - 1) + piles[j])
else: # 轮到李选
dp[i][j] = min(cal(i + 1, j) - piles[i], cal(i, j - 1) - piles[j])
return dp[i][j]
cal(0, len(piles) - 1)
return True if dp[0][len(piles) - 1] else False
c++ code
class Solution {
public:
int CacuDiffer(vector<int>& piles, vector<vector<int>>& dp, int i, int j){
if(dp[i][j]) return dp[i][j]; //dp[i][j]有数据直接返回
else if(i + 1 == j){ //只有两堆的时候
dp[i][j] = max(piles[i], piles[j]);
return dp[i][j];
}
else{
if((j - i) % 2) //当是ya在选择的时候
dp[i][j] = max(CacuDiffer(piles, dp, i + 1, j) + piles[i], CacuDiffer(piles, dp, i, j - 1) + piles[j]);
else
dp[i][j] = min(CacuDiffer(piles, dp, i + 1, j) - piles[i], CacuDiffer(piles, dp, i, j - 1) - piles[j]);
return dp[i][j];
}
}
bool stoneGame(vector<int>& piles) {
vector<vector<int>> dp(piles.size(), vector<int>(piles.size())); //动归数组,记录差值
CacuDiffer(piles, dp, 0, piles.size() - 1);
return dp[0][piles.size() - 1] > 0 ? true : false;
}
};