算法中的博弈论——石头游戏

原题链接
石头游戏
题目描述
亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 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、石头的堆数是偶数,这一点说明双方进行的轮次相等
2、石头的总数是奇数,也就是说双方最后总能取出不一样的石头数(必分胜负)
3、玩家亚历克斯为先手,当先手获胜时返回true,否则为false;
4、亚历克斯和李两个玩家都发挥出最佳水平
5、玩家只能选择首尾两端的石头堆

我们先以上述的输入为例:

输入:[5,3,4,5]
输出:true

这个输入样例总能够分出石头总数不一样的两堆:
第一种:

亚历克斯
第一轮 取第一堆 取第四堆
第二论 取第三堆 取第二堆

第二种:

亚历克斯
第一轮 取第四堆 取第一堆
第二轮 取第三堆 取第二堆


其实第二种情况的分析并无太多意义,对于每一种输入样例,先手(亚历克斯)总能决定自己选择偶数堆(即第二、四堆)还是奇数堆(即第一、三堆);

证明:如果亚历克斯先选的第一堆,则剩下第二、三、四堆,无论李怎么选择,总会将奇数堆(第三堆)暴露在两端;
如果亚历克斯先选第四堆,则可供李选择的有第一、二、三堆,无论李如何选择,总会将偶数堆(第二堆)暴露于两端;

由于石头总数是奇数,所以对于偶数堆和奇数堆的石头数总是不一样的,所以先手(亚历克斯)总会先判断到底是偶数堆石头数更多还是奇数堆石头总数更多,然后再去选择必胜的一条路径!

所以这个游戏就变得非常容易;

代码如下:

class Solution {
public:
    bool stoneGame(vector<int>& piles) {
        return true;
    }
};

看完了上面的题目,大家对于是否觉得算法中的博弈论非常有趣?这里在给出几道,大家可以思考一下:
题目描述
定义一串以数字8开头的,长度为11的数字为电话号码!现给定一串数字的长度为n(n大于11且n为奇数),和一个储存该数字串的字符串s,玩家A和玩家B轮流从这串数字中剔除一个数字;玩家A先开始,直到数字串长度减为11为止,如果此时数字串以数字8开头(即为一串电话号码),则玩家A获胜!否则玩家B获胜!
题目的要求就是让你根据给定的数字串来判断玩家A是否可以必胜!,意思就是无论玩家B怎么操作,最后剩下的数字串肯定是一个电话号码!这里假设双方玩家都足够聪明!

示例
Input

13
8380011223344

Output

YES

Input

15
807345619350641

Output

NO

Note

In the first example Vasya needs to erase the second character. Then Petya cannot erase a character from the remaining string 880011223344 so that it does not become a telephone number.

In the second example after Vasya’s turn Petya can erase one character character 8. The resulting string can’t be a telephone number, because there is no digit 8 at all.

大家先慢慢思考,后续会给出解法!还有更多类似的算法题目,如果你感兴趣的话可以关注我的微信公众号:艺千秋录
算法中的博弈论——石头游戏_第1张图片

你可能感兴趣的:(刷题宝典)