2023-07-05:爱丽丝和鲍勃继续他们的石子游戏

许多堆石子 排成一行,每堆都有正整数颗石子 piles[i]

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

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

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

然后,令 M = max(M, X)。

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

假设爱丽丝和鲍勃都发挥出最佳水平W

返回爱丽丝可以得到的最大数量的石头。

输入:piles = [2,7,9,4,4]。

输出:10。

答案2023-07-05:

1.算法 stoneGameII1:暴力方法

  • 首先定义函数 stoneGameII1,接收一个石子堆的切片 piles 作为参数,并返回爱丽丝可以得到的最大数量的石头。

  • 在函数 stoneGameII1 中调用函数 first1,并传入初始参数 piles、index=0(表示当前石子堆的索引)、m=1(表示当前的 M 值)。

  • 函数 first1 的作用是计算爱丽丝在当前石子堆的状态下的最优解。如果当前石子堆的索引达到了最后一个位置(即 index == len(piles)),则返回 0(石子已经全部取完)。

  • 否则,初始化变量 best = 0(当前的最优解)和 pre = 0(当前已经取走的石子数量)。

  • 开始一个循环,从当前索引开始遍历石子堆(i = index),并且用变量 j 记录当前取走的石子堆的数量(初始值为 1)。

  • 在循环中,更新变量 pre = pre + piles[i],即计算当前的已取走的石子数量。

  • 然后,根据当前的石子堆状态以及剩余可取的石子堆的数量(int(math.Max(float64(j), float64(m)))),调用函数 second1,并传入相应的参数,计算爱丽丝在下一轮的最优解。

  • 更新变量 best = int(math.Max(float64(best), float64(pre+second1(piles, i+1, int(math.Max(float64(j), float64(m))))))),即取当前轮最优解和已取走的石子数量之和的较大值作为当前的最优解。

  • 循环结束后,返回变量 best。

函数 second1 的作用是计算鲍勃在当前石子堆的状态下的最优解,其过程与函数 first1 类似。

  • 首先判断是否遍历到了最后一个石子堆,如果是,则返回 0(石子已全部取走)。
  • 否则,初始化变量 worse = math.MaxInt64(当前的最差解)。
  • 开始一个循环,从当前索引开始遍历石子堆,并用变量 j 记录当前取走的石子堆的数量(初始值为 1)。
  • 在循环中,更新变量 worse = int(math.Min(float64(worse), float64(first1(piles, i+1, int(math.Max(float64(j), float64(m))))))),即取当前轮最差解和已取走的石子数量之和的较小值作为当前的最差解。
  • 循环结束后,返回变量 worse。

2.算法 stoneGameII2:记忆化搜索

  • 首先定义函数 stoneGameII2,接收一个石子堆的切片 piles 作为参数,并返回爱丽丝可以得到的最大数量的石头。

  • 在函数 stoneGameII2 中,首先初始化变量 n 为石子堆的数量,创建两个二维切片 f 和 s,用于存储记忆化搜索的结果。

  • 利用循环,初始化 f 和 s 的值为 -1。

  • 调用函数 first2,并传入初始参数 piles、index=0(表示当前石子堆的索引)、m=1(表示当前的 M 值)、f 和 s。

  • 函数 first2 的作用是计算爱丽丝在当前石子堆的状态下的最优解,其过程类似函数 first1,但加入了记忆化搜索的机制。

  • 首先判断是否已经计算过该状态的结果,如果是,则直接返回存储的结果 f[index][m]。

  • 否则,继续计算最优解。

  • 在计算过程中,每一轮的最优解都会存储在 f[index][m],以避免重复计算。

  • 在循环中,需要调用函数 second2,传入相应的参数,计算鲍勃在当前石子堆的状态下的最优解,并存储在 s[i+1][int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m)))))] 中。

  • 循环结束后,将最优解保存到 f[index][m] 中,并返回最优解。

函数 second2 的作用是计算鲍勃在当前石子堆的状态下的最优解,与函数 second1 类似,但加入了记忆化搜索的机制。

  • 首先判断是否已经计算过该状态的结果,如果是,则直接返回存储的结果 s[index][m]。

  • 否则,继续计算最优解。

  • 在计算过程中,每一轮的最优解都会存储在 s[index][m],以避免重复计算。

  • 循环结束后,将最优解保存到 s[index][m] 中,并返回最优解。

3.算法 stoneGameII3:严格位置依赖的动态规划,一张表的版本

  • 首先定义函数 stoneGameII3,接收一个石子堆的切片 piles 作为参数,并返回爱丽丝可以得到的最大数量的石头。

  • 在函数 stoneGameII3 中,首先初始化变量 n 为石子堆的数量,创建两个二维切片 f 和 s,表示爱丽丝和鲍勃在每个石子堆的状态下的最优解。

  • 利用循环,初始化 f 和 s 的值为 0。

  • 初始化变量 sum = 0,用于记录累计的石子数。

  • 从最后一个石子堆开始循环,更新变量 sum = sum + piles[index],即计算当前的累计石子数。

  • 在循环中,根据动态规划的思想,计算爱丽丝和鲍勃的最优解。

  • 首先计算爱丽丝在当前石子堆状态下的最优解。

  • 声明变量 best = 0,表示当前的最优解。

  • 声明变量 pre = 0,表示当前已经取走的石子数量。

  • 在循环中,用变量 j 记录当前取走的石子堆的数量(初始值为 1)。

  • 在循环中,更新变量 pre = pre + piles[i],即计算当前的已取走的石子数量。

  • 根据当前的石子堆状态以及剩余可取的石子堆的数量(int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m)))))),计算爱丽丝在下一轮的最优解 s[i+1][int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m)))))]。

  • 更新变量 best = int(math.Max(float64(best), float64(pre+s[i+1][int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m)))))]))),取当前轮最优解和已取走的石子数量之和的较大值作为当前的最优解。

  • 计算鲍勃在当前石子堆状态下的最优解。

  • 声明变量 worse = math.MaxInt64,表示当前的最差解。

  • 在循环中,用变量 j 记录当前取走的石子堆的数量(初始值为 1)。

  • 在循环中,更新变量 worse = int(math.Min(float64(worse), float64(f[i+1][int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m)))))]))),取当前轮最差解和已取走的石子数量之和的较小值作为当前的最差解。

  • 循环结束后,更新 f[index][m] = best 和 s[index][m] = worse。

  • 返回 f[0][1],即爱丽丝在初始状态下的最优解。

4.算法 stoneGameII4:严格位置依赖的动态规划

  • 首先定义函数 stoneGameII4,接收一个石子堆的切片 piles 作为参数,并返回爱丽丝可以得到的最大数量的石头。

  • 在函数 stoneGameII4 中,首先初始化变量 n 为石子堆的数量,创建一个二维切片 dp,用于存储动态规划的结果。

  • 利用循环,初始化 dp 的值为 0。

  • 初始化变量 sum = 0,用于记录累计的石子数。

  • 从最后一个石子堆开始循环,更新变量 sum = sum + piles[i],即计算当前的累计石子数。

  • 在循环中,根据动态规划的思想,计算爱丽丝的最优。

stoneGameII1的时间复杂度为$O(2^n)$,空间复杂度为$O(n)$。

stoneGameII2的时间复杂度为$O(n3)$,空间复杂度为$O(n2)$。

stoneGameII3的时间复杂度为$O(n3)$,空间复杂度为$O(n2)$。

stoneGameII4的时间复杂度为$O(n^2)$,空间复杂度为$O(n)$。

go完整代码如下:

package main

import (
"fmt"
"math"
) // 暴力方法
func stoneGameII1(piles []int) int {
return first1(piles, 0, 1)
} func first1(piles []int, index, m int) int {
if index == len(piles) {
return 0
}
best := 0
pre := 0
for i, j := index, 1; i < len(piles) && j <= 2*m; i, j = i+1, j+1 {
pre += piles[i]
best = int(math.Max(float64(best), float64(pre+second1(piles, i+1, int(math.Max(float64(j), float64(m)))))))
}
return best
} func second1(piles []int, index, m int) int {
if index == len(piles) {
return 0
}
worse := math.MaxInt64
for i, j := index, 1; i < len(piles) && j <= 2*m; i, j = i+1, j+1 {
worse = int(math.Min(float64(worse), float64(first1(piles, i+1, int(math.Max(float64(j), float64(m)))))))
}
return worse
} // 记忆化搜索
func stoneGameII2(piles []int) int {
n := len(piles)
f := make([][]int, n)
s := make([][]int, n)
for i := 0; i < n; i++ {
f[i] = make([]int, n+1)
s[i] = make([]int, n+1)
for j := 0; j <= n; j++ {
f[i][j] = -1
s[i][j] = -1
}
}
return first2(piles, 0, 1, f, s)
} func first2(piles []int, index, m int, f, s [][]int) int {
if index == len(piles) {
return 0
}
if f[index][m] != -1 {
return f[index][m]
}
best := 0
pre := 0
for i, j := index, 1; i < len(piles) && j <= 2*m; i, j = i+1, j+1 {
pre += piles[i]
best = int(math.Max(float64(best), float64(pre+second2(piles, i+1, int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m))))), f, s))))
}
f[index][m] = best
return best
} func second2(piles []int, index, m int, f, s [][]int) int {
if index == len(piles) {
return 0
}
if s[index][m] != -1 {
return s[index][m]
}
worse := math.MaxInt64
for i, j := index, 1; i < len(piles) && j <= 2*m; i, j = i+1, j+1 {
worse = int(math.Min(float64(worse), float64(first2(piles, i+1, int(math.Min(float64(len(piles)), float64(math.Max(float64(j), float64(m))))), f, s))))
}
s[index][m] = worse
return worse
} // 严格位置依赖的动态规划,一张表的版本
func stoneGameII3(piles []int) int {
n := len(piles)
f := make([][]int, n+1)
s := make([][]int, n+1)
for i := 0; i <= n; i++ {
f[i] = make([]int, n+1)
s[i] = make([]int, n+1)
}
sum := 0
for index := n - 1; index >= 0; index-- {
sum += piles[index]
for m := 1; m <= n; m++ {
best := 0
pre := 0
for i, j := index, 1; i < len(piles) && j <= 2*m; i, j = i+1, j+1 {
pre += piles[i]
best = int(math.Max(float64(best), float64(pre+s[i+1][int(math.Min(float64(n), float64(math.Max(float64(j), float64(m)))))])))
}
f[index][m] = best
worse := math.MaxInt64
for i, j := index, 1; i < len(piles) && j <= 2*m; i, j = i+1, j+1 {
worse = int(math.Min(float64(worse), float64(f[i+1][int(math.Min(float64(n), float64(math.Max(float64(j), float64(m)))))])))
}
s[index][m] = worse
}
}
return f[0][1]
} // 严格位置依赖的动态规划
func stoneGameII4(piles []int) int {
n := len(piles)
sum := 0
dp := make([][]int, n)
for i := range dp {
dp[i] = make([]int, n+1)
}
for i := n - 1; i >= 0; i-- {
sum += piles[i]
for m := 1; m <= n; m++ {
if i+2*m >= n {
dp[i][m] = sum
} else {
nextMin := math.MaxInt64
for x := 1; x <= 2*m; x++ {
nextMin = int(math.Min(float64(nextMin), float64(dp[i+x][int(math.Max(float64(m), float64(x)))])))
}
dp[i][m] = sum - nextMin
}
}
}
return dp[0][1]
} func main() {
piles := []int{2, 7, 9, 4, 4}
fmt.Println("stoneGameII1:", stoneGameII1(piles))
fmt.Println("stoneGameII2:", stoneGameII2(piles))
fmt.Println("stoneGameII3:", stoneGameII3(piles))
fmt.Println("stoneGameII4:", stoneGameII4(piles))
}

rust完整代码如下:

fn stone_game_ii1(piles: Vec<i32>) -> i32 {
first1(&piles, 0, 1)
} fn first1(piles: &Vec<i32>, index: usize, m: i32) -> i32 {
if index == piles.len() {
return 0;
}
let mut best = 0;
let mut pre = 0;
for i in index..piles.len().min(index + (2 * m) as usize) {
pre += piles[i];
best = best.max(pre + second1(piles, i + 1, m.max(i as i32 + 1)));
}
best
} fn second1(piles: &Vec<i32>, index: usize, m: i32) -> i32 {
if index == piles.len() {
return 0;
}
let mut worse = i32::MAX;
for i in index..piles.len().min(index + (2 * m) as usize) {
worse = worse.min(first1(piles, i + 1, m.max(i as i32 + 1)));
}
worse
} fn stone_game_ii2(piles: Vec<i32>) -> i32 {
let mut f = vec![vec![-1; piles.len() + 1]; piles.len()];
let mut s = vec![vec![-1; piles.len() + 1]; piles.len()]; first2(&piles, 0, 1, &mut f, &mut s)
} fn first2(
piles: &Vec<i32>,
index: usize,
m: usize,
f: &mut Vec<Vec<i32>>,
s: &mut Vec<Vec<i32>>,
) -> i32 {
if index == piles.len() {
return 0;
}
if f[index][m] != -1 {
return f[index][m];
}
let mut best = 0;
let mut pre = 0;
for i in index..piles.len().min(index + 2 * m) {
pre += piles[i];
best = best.max(pre + second2(piles, i + 1, m.max(i - index + 1), f, s));
}
f[index][m] = best;
best
} fn second2(
piles: &Vec<i32>,
index: usize,
m: usize,
f: &mut Vec<Vec<i32>>,
s: &mut Vec<Vec<i32>>,
) -> i32 {
if index == piles.len() {
return 0;
}
if s[index][m] != -1 {
return s[index][m];
}
let mut worse = i32::MAX;
for i in index..piles.len().min(index + 2 * m) {
worse = worse.min(first2(piles, i + 1, m.max(i - index + 1), f, s));
}
s[index][m] = worse;
worse
} fn stone_game_ii3(piles: Vec<i32>) -> i32 {
let n = piles.len();
let mut f: Vec<Vec<i32>> = vec![vec![0; n + 1]; n + 1];
let mut s: Vec<Vec<i32>> = vec![vec![0; n + 1]; n + 1]; for index in (0..n).rev() {
for m in 1..=n {
let mut pre = 0;
for (i, j) in (index..piles.len()).zip(1..=2 * m) {
pre += piles[i];
f[index][m] = f[index][m].max(pre + s[i + 1][n.min(j.max(m))]);
} s[index][m] = i32::MAX;
for (i, j) in (index..piles.len()).zip(1..=2 * m) {
s[index][m] = s[index][m].min(f[i + 1][n.min(j.max(m))]);
}
}
} f[0][1]
} fn stone_game_ii4(piles: Vec<i32>) -> i32 {
let n = piles.len();
let mut sum = 0;
let mut dp = vec![vec![0; n + 1]; n]; for i in (0..n).rev() {
sum += piles[i];
for m in 1..=n {
if i + 2 * m >= n {
dp[i][m] = sum;
} else {
let mut next_min = std::i32::MAX;
for x in 1..=2 * m {
next_min = next_min.min(dp[i + x][m.max(x)]);
}
dp[i][m] = sum - next_min;
}
}
} dp[0][1]
} fn main() {
let piles = vec![2, 7, 9, 4, 4];
let result = stone_game_ii1(piles);
println!("{}", result); let piles = vec![2, 7, 9, 4, 4];
let result = stone_game_ii2(piles);
println!("{}", result); let piles = vec![2, 7, 9, 4, 4];
let result = stone_game_ii3(piles);
println!("{}", result); let piles = vec![2, 7, 9, 4, 4];
let result = stone_game_ii4(piles);
println!("{}", result);
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits> using namespace std; int second1(vector<int>& piles, int index, int m); int first1(vector<int>& piles, int index, int m) {
if (index == piles.size()) {
return 0;
}
int best = 0;
int pre = 0;
for (int i = index, j = 1; i < piles.size() && j <= 2 * m; i++, j++) {
pre += piles[i];
best = max(best, pre + second1(piles, i + 1, max(j, m)));
}
return best;
} int second1(vector<int>& piles, int index, int m) {
if (index == piles.size()) {
return 0;
}
int worse = INT_MAX;
for (int i = index, j = 1; i < piles.size() && j <= 2 * m; i++, j++) {
worse = min(worse, first1(piles, i + 1, max(j, m)));
}
return worse;
} int stoneGameII1(vector<int>& piles) {
return first1(piles, 0, 1);
} int second2(vector<int>& piles, int index, int m, vector<vector<int>>& f, vector<vector<int>>& s); int first2(vector<int>& piles, int index, int m, vector<vector<int>>& f, vector<vector<int>>& s) {
if (index == piles.size()) {
return 0;
}
if (f[index][m] != -1) {
return f[index][m];
}
int best = 0;
int pre = 0;
for (int i = index, j = 1; i < piles.size() && j <= 2 * m; i++, j++) {
pre += piles[i];
best = max(best, pre + second2(piles, i + 1, min((int)piles.size(), max(j, m)), f, s));
}
f[index][m] = best;
return best;
} int second2(vector<int>& piles, int index, int m, vector<vector<int>>& f, vector<vector<int>>& s) {
if (index == piles.size()) {
return 0;
}
if (s[index][m] != -1) {
return s[index][m];
}
int worse = INT_MAX;
for (int i = index, j = 1; i < piles.size() && j <= 2 * m; i++, j++) {
worse = min(worse, first2(piles, i + 1, min((int)piles.size(), max(j, m)), f, s));
}
s[index][m] = worse;
return worse;
} int stoneGameII2(vector<int>& piles) {
int n = piles.size();
vector<vector<int>> f(n, vector<int>(n + 1, -1));
vector<vector<int>> s(n, vector<int>(n + 1, -1));
return first2(piles, 0, 1, f, s);
} int stoneGameII3(vector<int>& piles) {
int n = piles.size();
vector<vector<int>> f(n + 1, vector<int>(n + 1, 0));
vector<vector<int>> s(n + 1, vector<int>(n + 1, 0)); for (int index = n - 1; index >= 0; index--) {
for (int m = 1; m <= n; m++) {
int pre = 0;
for (int i = index, j = 1; i < n && j <= 2 * m; i++, j++) {
pre += piles[i];
f[index][m] = max(f[index][m], pre + s[i + 1][min(n, max(j, m))]);
}
s[index][m] = INT_MAX;
for (int i = index, j = 1; i < n && j <= 2 * m; i++, j++) {
s[index][m] = min(s[index][m], f[i + 1][min(n, max(j, m))]);
}
}
}
return f[0][1];
} int stoneGameII4(vector<int>& piles) {
int n = piles.size();
int sum = 0;
vector<vector<int>> dp(n, vector<int>(n + 1, 0));
for (int i = n - 1; i >= 0; i--) {
sum += piles[i];
for (int m = 1; m <= n; m++) {
if (i + 2 * m >= n) {
dp[i][m] = sum;
}
else {
int nextMin = INT_MAX;
for (int x = 1; x <= 2 * m; x++) {
nextMin = min(nextMin, dp[i + x][max(m, x)]);
}
dp[i][m] = sum - nextMin;
}
}
}
return dp[0][1];
} int main() {
vector<int> piles = { 2, 7, 9, 4, 4 };
cout << "stoneGameII1: " << stoneGameII1(piles) << endl;
cout << "stoneGameII2: " << stoneGameII2(piles) << endl;
cout << "stoneGameII3: " << stoneGameII3(piles) << endl;
cout << "stoneGameII4: " << stoneGameII4(piles) << endl;
return 0;
}

c完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h> int second1(int* piles, int pilesSize, int index, int m); int first1(int* piles, int pilesSize, int index, int m) {
if (index == pilesSize) {
return 0;
}
int best = 0;
int pre = 0;
for (int i = index, j = 1; i < pilesSize && j <= 2 * m; i++, j++) {
pre += piles[i];
best = best > (pre + second1(piles, pilesSize, i + 1, j > m ? j : m)) ? best : (pre + second1(piles, pilesSize, i + 1, j > m ? j : m));
}
return best;
} int second1(int* piles, int pilesSize, int index, int m) {
if (index == pilesSize) {
return 0;
}
int worse = INT_MAX;
for (int i = index, j = 1; i < pilesSize && j <= 2 * m; i++, j++) {
worse = worse < first1(piles, pilesSize, i + 1, j > m ? j : m) ? worse : first1(piles, pilesSize, i + 1, j > m ? j : m);
}
return worse;
} int stoneGameII1(int* piles, int pilesSize) {
return first1(piles, pilesSize, 0, 1);
} int second2(int* piles, int pilesSize, int index, int m, int** f, int** s); int first2(int* piles, int pilesSize, int index, int m, int** f, int** s) {
if (index == pilesSize) {
return 0;
}
if (f[index][m] != -1) {
return f[index][m];
}
int best = 0;
int pre = 0;
for (int i = index, j = 1; i < pilesSize && j <= 2 * m; i++, j++) {
pre += piles[i];
best = best > (pre + second2(piles, pilesSize, i + 1, j > m ? j : m, f, s)) ? best : (pre + second2(piles, pilesSize, i + 1, j > m ? j : m, f, s));
}
f[index][m] = best;
return best;
} int second2(int* piles, int pilesSize, int index, int m, int** f, int** s) {
if (index == pilesSize) {
return 0;
}
if (s[index][m] != -1) {
return s[index][m];
}
int worse = INT_MAX;
for (int i = index, j = 1; i < pilesSize && j <= 2 * m; i++, j++) {
worse = worse < first2(piles, pilesSize, i + 1, j > m ? j : m, f, s) ? worse : first2(piles, pilesSize, i + 1, j > m ? j : m, f, s);
}
s[index][m] = worse;
return worse;
} int stoneGameII2(int* piles, int pilesSize) {
int n = pilesSize;
int** f = (int**)malloc((n + 1) * sizeof(int*));
int** s = (int**)malloc((n + 1) * sizeof(int*));
for (int i = 0; i < n; i++) {
f[i] = (int*)malloc((n + 1) * sizeof(int));
s[i] = (int*)malloc((n + 1) * sizeof(int));
for (int j = 0; j <= n; j++) {
f[i][j] = -1;
s[i][j] = -1;
}
}
return first2(piles, pilesSize, 0, 1, f, s);
} int stoneGameII3(int* piles, int pilesSize) {
int n = pilesSize;
int** f = (int**)malloc((n + 1) * sizeof(int*));
int** s = (int**)malloc((n + 1) * sizeof(int*));
for (int i = 0; i <= n; i++) {
f[i] = (int*)malloc((n + 1) * sizeof(int));
s[i] = (int*)malloc((n + 1) * sizeof(int));
for (int j = 0; j <= n; j++) {
f[i][j] = 0;
s[i][j] = 0;
}
} for (int index = n - 1; index >= 0; index--) {
for (int m = 1; m <= n; m++) {
int pre = 0;
for (int i = index, j = 1; i < n && j <= 2 * m; i++, j++) {
pre += piles[i];
f[index][m] = f[index][m] > (pre + s[i + 1][j > m ? j : m]) ? f[index][m] : (pre + s[i + 1][j > m ? j : m]);
}
s[index][m] = INT_MAX;
for (int i = index, j = 1; i < n && j <= 2 * m; i++, j++) {
s[index][m] = s[index][m] < f[i + 1][j > m ? j : m] ? s[index][m] : f[i + 1][j > m ? j : m];
}
}
}
return f[0][1];
} int stoneGameII4(int* piles, int pilesSize) {
int n = pilesSize;
int sum = 0;
int** dp = (int**)malloc(n * sizeof(int*));
for (int i = 0; i < n; i++) {
dp[i] = (int*)malloc((n + 1) * sizeof(int));
for (int j = 0; j <= n; j++) {
dp[i][j] = 0;
}
}
for (int i = n - 1; i >= 0; i--) {
sum += piles[i];
for (int m = 1; m <= n; m++) {
if (i + 2 * m >= n) {
dp[i][m] = sum;
}
else {
int nextMin = INT_MAX;
for (int x = 1; x <= 2 * m; x++) {
nextMin = nextMin < dp[i + x][m > x ? m : x] ? nextMin : dp[i + x][m > x ? m : x];
}
dp[i][m] = sum - nextMin;
}
}
}
return dp[0][1];
} int main() {
int piles[] = { 2, 7, 9, 4, 4 };
int pilesSize = sizeof(piles) / sizeof(piles[0]);
printf("stoneGameII1: %d\n", stoneGameII1(piles, pilesSize));
printf("stoneGameII2: %d\n", stoneGameII2(piles, pilesSize));
printf("stoneGameII3: %d\n", stoneGameII3(piles, pilesSize));
printf("stoneGameII4: %d\n", stoneGameII4(piles, pilesSize));
return 0;
}

2023-07-05:爱丽丝和鲍勃继续他们的石子游戏 许多堆石子 排成一行,每堆都有正整数颗石子 piles[i] 游戏以谁手中的石子最多来决出胜负。 爱丽丝和鲍勃轮流进行,爱丽丝先开始。最初,的更多相关文章

  1. 2019.07.05 纪中_B

    今日膜拜:czj大佬orz%%% 2019.07.05[NOIP提高组]模拟 B 组 今天做题的时候大概能判断出题人的考点,可是就是没学过...特别痛苦 T0:栈的定义,模拟就好了T1:感觉像是找规律 ...

  2. Murano Weekly Meeting 2016.07.05

    Meeting time: 2016.July.05 1:00~2:00 Chairperson:  Kirill Zaitsev, from Mirantis Meeting summary: 1. ...

  3. <2013 07 05> 804.15. 4--> TI MSP430+CC2520 调试

    这一周,实际参与eCar项目的工作正式展开. 来TUM的第一个月,主要熟悉了eCar的机电结构,特别是熟悉了eCar的IT(Information Technology),包括硬件和代码. 来的时候, ...

  4. 2016/07/05 zend optimizer

    Zend Optimizer是由PHP核心引擎“Zend” http://www.zend.com 创建者Zend技术公司所开的免费PHP优化软件.据Zend公司透露使用这个软件某些情况下至少可以提高 ...

  5. 1140. 石子游戏 II (Medium)

    问题描述 1140. 石子游戏 II (Medium) 爱丽丝和鲍勃继续他们的石子游戏.许多堆石子 排成一行,每堆都有正整数颗石子 piles[i].游戏以谁手中的石子最多来决出胜负. 爱丽丝和鲍勃轮 ...

  6. [Swift]LeetCode877. 石子游戏 | Stone Game

    Alex and Lee play a game with piles of stones.  There are an even number of piles arranged in a row, ...

  7. Bit Operation妙解算法题

    5道巧妙位操作的算法题. ***第一道*** 题目描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. ...

  8. leetcode 877. 石子游戏

    题目描述: 亚历克斯和李用几堆石子在做游戏.偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] . 游戏以谁手中的石子最多来决出胜负.石子的总数是奇数,所以没有平局. 亚历克斯和李轮流进行,亚 ...

  9. Leetcode之动态规划(DP)专题-877. 石子游戏(Stone Game)

    Leetcode之动态规划(DP)专题-877. 石子游戏(Stone Game) 亚历克斯和李用几堆石子在做游戏.偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] . 游戏以谁手中的石子最 ...

  10. leetcode 877. Stone Game 详解 -——动态规划

    原博客地址 https://blog.csdn.net/androidchanhao/article/details/81271077 题目链接 https://leetcode.com/proble ...

随机推荐

  1. 基于SpringBoot实现单元测试的多种情境/方法(二)

    本文分享自天翼云开发者社区@<基于SpringBoot实现单元测试的多种情境/方法(二)>,  作者:才开始学技术的小白 1 Mock基础回顾 在上一篇分享中我们详细介绍了简单的.用moc ...

  2. ditto 添加统计粘贴次数功能

    通过观察ditto的表发现, 可以添加触发器进行统计粘贴次数的功能,不需要用源码 Ditto 是一款强大的 Windows 剪贴板增强工具,它支持64位操作系统,而且完全免费,绿色开源,支持中文,而且 ...

  3. ChatCLM部署随笔

    ChatCLM 博客 ChatGLM Github ChatGLM-webui 介绍 ChatGLM-6B 是一个开源的.支持中英双语的对话语言模型,基于 General Language Model ...

  4. Django笔记二十四之数据库函数之比较和转换函数

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十四之数据库函数之比较和转换函数 这一篇笔记开始介绍几种数据库函数,以下是几种函数及其作用 Cast 转换类型 Coalesce 优先取 ...

  5. 关于 OAuth 你又了解哪些?

    作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者. OAuth 的背景 OAuth,O 是 Open,Au ...

  6. JS执行机制--同步与异步

    单线程JavaScript语言具有单线程的特点,同一个时间只能做一件事情.这是因为JavaScript脚本语言是为了处理页面中用户的交互,以及操作DOM而诞生的.如果对某个DOM元素进行添加和删除,不 ...

  7. python_7 退出、结束循环和嵌套循环

    一.查缺补漏 1. end=' 任意值 ' 表示换行,任意值会显示在换行前,不写默认换行 2. input() 用户键盘输入 默认输入str类型,如要和int类型比较需要强制类型转换二.退出.结束循环 ...

  8. Java中数字相关的类有哪些?Nuber数字类和Math数学类详解

    前言 我们在解决实际问题时,会经常对数字.日期和系统设置进行处理,比如在我们的代码中,经常会遇到一些数字&数学问题.随机数问题.日期问题和系统设置问题等. 为了解决这些问题,Java给我们提供 ...

  9. Typora+MinIO+Python代码打造舒适协作环境

    作者:IT王小二 博客:https://itwxe.com 不知不觉大半年没更新了...前面小二介绍过使用Typora+MinIO+Java代码打造舒适写作环境,然后有很多大佬啊,说用Java来实现简 ...

  10. 2023-03-22:给定一个字符串str, 如果删掉连续一段子串,剩下的字符串拼接起来是回文串, 那么该删除叫做有效的删除。 返回有多少种有效删除。 注意 : 不能全删除,删成空串不允许, 字符串长

    2023-03-22:给定一个字符串str, 如果删掉连续一段子串,剩下的字符串拼接起来是回文串, 那么该删除叫做有效的删除. 返回有多少种有效删除. 注意 : 不能全删除,删成空串不允许, 字符串长 ...