问题描述

1140. 石子游戏 II (Medium)

爱丽丝和鲍勃继续他们的石子游戏。许多堆石子 排成一行,每堆都有正整数颗石子

piles[i]。游戏以谁手中的石子最多来决出胜负。

爱丽丝和鲍勃轮流进行,爱丽丝先开始。最初, M = 1

在每个玩家的回合中,该玩家可以拿走剩下的 X 堆的所有石子,其中 1 <= X <= 2M。然后,令

M = max(M, X)

游戏一直持续到所有石子都被拿走。

假设爱丽丝和鲍勃都发挥出最佳水平,返回爱丽丝可以得到的最大数量的石头。

示例 1:

输入:piles = [2,7,9,4,4]
输出:10
解释:如果一开始Alice取了一堆,Bob取了两堆,然后Alice再取两堆。爱丽丝可以得到2 + 4 + 4 =
10堆。如果Alice一开始拿走了两堆,那么Bob可以拿走剩下的三堆。在这种情况下,Alice得到2 + 7 =
9堆。返回10,因为它更大。

示例 2:

输入:piles = [1,2,3,4,5,100]
输出:104

提示:

  • 1 <= piles.length <= 100
  • 1 <= piles[i] <= 10⁴

解题思路

首先这里要明确发挥最佳水平的含义:

如果自己拿了前x块石子之后,对方所能拿到的石子最少,这就是博弈中的发挥最佳水平,对应到dfs,明白了这一点就能写出递归和记忆化搜索,注意这里还需要用到后缀数组。

写出记忆化搜索之后可以改写成动态规划。

代码

记忆化搜索

class Solution {
public:
int dfs(int idx_start, int M, vector<int> &postfix, int n, vector<vector<int>> &cach) {
if (idx_start >= n)
return 0; int minnum = 100001;
if (cach[idx_start][M] >= 0) {
return cach[idx_start][M];
}
for (int i = idx_start + 1; i <= idx_start + 2 * M && i <= n; i++) { // i表示下一个人拿石子的开始位置,所以i至少为idx_start+1
int tmp = dfs(i, std::max(i - idx_start, M), postfix, n, cach);
if (minnum > tmp) {
minnum = tmp;
}
}
cach[idx_start][M] = postfix[idx_start] - minnum;
return cach[idx_start][M]; }
int stoneGameII(vector<int>& piles) {
int n = piles.size();
vector<int> postfix(n + 1, 0);
for (int i = n - 1; i >= 0; i--) {
postfix[i] = postfix[i + 1] + piles[i];
}
vector<vector<int>> cach(n + 1, vector<int>(n, -1));
return dfs(0, 1, postfix, n, cach);
}
};

动态规划

class Solution {
public:
int stoneGameII(vector<int> &piles) {
int n = piles.size();
vector<int> postfix(n + 1, 0);
// 后缀和数组
for (int i = n - 1; i >= 0; i--) {
postfix[i] = postfix[i + 1] + piles[i];
}
// dp[i][j]表示从坐标`i`开始拿`j`个所能获得的最大石子数
vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
for (int i = n - 1; i >= 0; i--) {
for (int M = 1; M <= i / 2 + 1; M++) {
if (i + 2 * M >= n) { // 说明可以直接拿走剩余的石子
dp[i][M] = postfix[i];
} else {
int min_num = INT_MAX;
for (int x = 1; x <= 2 * M; x++) {
// 因为从dp[i + x]递推到dp[i],所以`i`要倒序循环
min_num = std::min(min_num, dp[i + x][std::max(M, x)]);
}
dp[i][M] = postfix[i] - min_num;
}
}
}
return dp[0][1];
}
};

1140. 石子游戏 II (Medium)的更多相关文章

  1. BZOJ 1115: [POI2009]石子游戏Kam

    1115: [POI2009]石子游戏Kam Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 883  Solved: 545[Submit][Stat ...

  2. XDU 1161 - 科协的数字游戏II

    Problem 1161 - 科协的数字游戏II Time Limit: 1000MS   Memory Limit: 65536KB   Difficulty: Total Submit: 112  ...

  3. Games:取石子游戏(POJ 1067)

    取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37662   Accepted: 12594 Descripti ...

  4. {CSDN}{英雄会}{砍树、石子游戏}

    砍树 思路: 可以将题目意图转化为:给定一棵树,求其中最接近总权值一半的子树. DFS求每个节点的所有子节点的权值和,遍历每个节点,最接近总权值一半的即为答案.复杂度O(N). 石子游戏: 思路: 一 ...

  5. HDU 2176 取(m堆)石子游戏(Nim)

    取(m堆)石子游戏 题意: Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,1 ...

  6. HDU 2516 取石子游戏(斐波那契博弈)

    取石子游戏 Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  7. lintcode: 跳跃游戏 II

    跳跃游戏 II 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 样例 给出数组A =  ...

  8. hdu 1527 取石子游戏(Wythoff Game)

    题意:Wythoff Game 思路:Wythoff Game #include<iostream> #include<stdio.h> #include<math.h& ...

  9. HDU 2516 取石子游戏(FIB博弈)

    取石子游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  10. hdu 2176 取(m)石子游戏

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2176 题意分析:给出M堆石子,两人交替取子,给出先手能否胜利. 不能输出No, 能则输出Yes并给出第 ...

随机推荐

  1. css实现一个冰墩墩

    一墩难求,花了一两个小时自己画了一个,HTML结构很简单,CSS上主要就是将各个位置定位,肚子上的logo就只有发挥啦 以下是HTML代码 <div class="container& ...

  2. 2022-05-16内部群每日三题-清辉PMP

    1.项目可交付成果已移交给客户,项目经理现在必须收集项目参与者的反馈意见.项目经理应该查阅哪份文件来确定哪些人应该被包含进请求反馈意见的名单中? A.相关方登记册 B.沟通管理计划 C.经验教训 D. ...

  3. springcloud zuul网关整合swagger2,swagger被拦截问题

    首先感谢一位博主的分享https://www.cnblogs.com/xiaohouzai/p/8886671.html 话不多说直接上图和代码 首先我们要有一个springcloud分布式项目 我就 ...

  4. 其他6-break,continue,exit,return区别

    break.continue.exit.return的区别 break 跳出整个循环语句 continue 跳过本次循环,进入下一次循环语句 exit n 退出当前shell,并返回状态值 retur ...

  5. js复选框,三层结构

    最终实现效果如下 html+css如下 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 < ...

  6. Linux_CMD_FOR_FILE&FOLDER

    0,删除文件夹和子文件夹:rm -rf /xxx/xxx 0,拷贝整个文件夹:cp -r /xxx/xxx /ddd/ 0,改文件名:mv oldName newName 0,新建文件:touch f ...

  7. [部署日记]GO在Visual Studio Code初次运行时提示go: go.mod file not found in current directory or any parent directory; see 'go help modules'

    我裂开,一波未平一波又起... 按照MS教程上填写 package main import "fmt" func main() { fmt.Println("Hello ...

  8. VKM4 批准功能对应 bapi

    追踪代码发现function都在这里, SD_ORDER_CREDIT_RELEASE RVALVFORMS CALL FUNCTION 'MESSAGE_TEXT_BUILD'    EXPORTI ...

  9. 【小白必经之路:玩转STL】array容器

    此篇随笔将示范array容器的基本操作 1.介绍 array容器在C++普通数组的基础上,添加了一些函数.在使用上,它比普通数组更安全. 2.头文件及命名空间 1 #include<array& ...

  10. appium+python测试Android真机功能报错处理

    用Appium1.4.16.1测试Android8.1.0出现以下报错: C:\ProgramData\Anaconda3\python.exe D:/python/appium_learn/calc ...