零和博弈
概念介绍
零和博弈就是字面意思所表示的博弈情形,博弈双方在博弈过程中的总价值是不变的,双方某一方价值的增长必然会导致另一方价值的缩减,零和博弈是具有先手优势和后手劣势的。
- 先手优势
所谓先手优势其实指的是博弈双方具有优先选择权的一方,具有优先选择的优势,他可以优先控制选择的走向。 - 后手劣势
后手劣势指的是博弈双方中,后手一方在选择时会受到先手优势的影响,尽管博弈双方都可以选择最有利于自己的顺序进行,但是后手是在先手制约下的最优选择,所以后手是博弈双方中具有劣势的一方。
总之零和博弈作为一种常见的博弈方式我们只需要记住两个重要点——①博弈总和不变;②博弈双方在自己的立场上都是选择最优的。
算法实例
来源:力扣(LeetCode)
链接:预测赢家
题目描述如下:
给定一个表示分数的非负整数数组。 玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。
给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。
题目分析:
分析题目我们发现,这是一道典型的零和博弈算法题,所以按照之前所说的两个重要点,我们可以得到以下思路:
-
按照博弈双方总是在自己的立场选择最优的解,那么意味着假如当前数组的左右两端序号分别为left和right,那么当前长度下当前做出选择的一方应当做出最有利于自己的选择,也即价值最大的选择。现在当前选择的一方可以选择的方案有拿left或者拿right两种选择,他选择其中一方的依据是使得自己的利益最大,问题是如何判断拿取left或者right后的利益呢?我们知道的是当前选择方选择left或者right中一个后,后一方在剩余的数组中选择也是最有利于他的,所以假如另外一方在之后的选择中选择了一个最优方案,该方案的最大利益我们也已经知晓了为S,那么我们该如何得到当前一方最大利益呢?
-
这就需要用到第二个重要点,零和博弈中博弈的总价值是不变的,所以当我们知道剩余数组中另一方的最优价值为S,那么当前选择方所获得的价值也就确定了——即剩余数组价值总和-S;但是由于当前方需要选择价值最大的策略,所以他需要在选择left或者right中做一个权衡,所以当前选择方的最大利益为max(选择left的利益+去掉left后的剩余数组价值总和-去掉left后另一方的最优选择,选择right的利益+去掉right后的剩余数组价值总和-去掉right后另一方的最优选择);
通过上面分析我们实际上已经可以得到算法实现了,按照这个思路主要有两种实现方式:
- 递归实现
class Solution {
public:
int sum(vector<int>& nums,int left,int right){
int a=0;
for(int i=left;i<=right;i++){
a=a+nums[i];
}
return a;
}
int DFS(vector<int> &nums,int left,int right){
if(left==right){
return nums[left];
}
return max(nums[left]+sum(nums,left+1,right)-DFS(nums,left+1,right),nums[right]+sum(nums,left,right-1)-DFS(nums,left,right-1));
}
bool PredictTheWinner(vector<int>& nums) {
int player1=DFS(nums,0