2023-05-09:石子游戏中,爱丽丝和鲍勃轮流进行自己的回合,爱丽丝先开始 。

有 n 块石子排成一排。

每个玩家的回合中,可以从行中 移除 最左边的石头或最右边的石头,

并获得与该行中剩余石头值之 和 相等的得分。当没有石头可移除时,得分较高者获胜。

鲍勃发现他总是输掉游戏(可怜的鲍勃,他总是输),

所以他决定尽力 减小得分的差值 。爱丽丝的目标是最大限度地 扩大得分的差值 。

给你一个整数数组 stones ,其中 stones[i] 表示 从左边开始 的第 i 个石头的值,

如果爱丽丝和鲍勃都 发挥出最佳水平 ,请返回他们 得分的差值 。

输入:stones = [5,3,1,4,2] 。

输出:6 。

答案2023-05-09:

该问题的解法有多种,下面分别对三个函数的实现过程进行详细描述。

1.递归版

该函数使用递归实现了石子游戏。首先计算出整个石子数组的和sum,然后调用f函数获取Alice获得的最大得分,再调用s函数获取Bob获得的最大得分,最终计算出差值并返回。

f函数表示当前轮到Alice操作,从L位置取走一个石头或从R位置取走一个石头的情况下,Alice能获得的最大得分。将这两种情况所获得的得分与对手(Bob)相比较,选择更优的方案。其中,对手的得分由s函数计算。

s函数表示当前轮到Bob操作,在剩余石子中选择一个最优的石子让Alice取走,并计算自己的得分。此处需要注意,当前是Bob在操作,但是得分却是Alice决定的,因为Alice可以在自己的回合中选择拿走哪一块石头,进而影响Bob的得分。

时间复杂度为$O(2^n)$,空间复杂度为$O(n)$,其中n是石头的数量。

因为在每一层递归中,都会有两种分支需要继续递归下去,所以总共会有2^n个叶子节点。另外,由于递归的深度最多为n层,所以需要O(n)的栈空间来存储每一层递归的状态。

2.动态规划版

该函数使用动态规划实现了石子游戏。首先计算出整个石子数组的前缀和presum,然后定义两个二维数组dpf和dps。其中,dpf[i][j]表示当只剩下第i到第j块石头时,先手(即Alice)能够获得的最大得分;dps[i][j]表示当只剩下第i到第j块石头时,后手(即Bob)能够获得的最大得分。

接着,从右下角开始倒序遍历数组,计算出dpf和dps数组的值。具体计算方法如下:

  • 当前轮到先手操作,先手可以选择拿走第i块石头或第j块石头。如果先手拿走了第i块石头,则后手只能在第i+1到第j块石头中进行选择,在这种情况下,先手能够获得的得分为sumLR - stones[i] + dps[L+1][R],其中sumLR表示第i到第j块石头的和,dps[L+1][R]表示后手在第i+1到第j块石头中能够获得的最大得分。如果先手拿走了第j块石头,则后手只能在第i到第j-1块石头中进行选择,在这种情况下,先手能够获得的得分为sumLR - stones[j] + dps[L][R-1],其中dps[L][R-1]表示后手在第i到第j-1块石头中能够获得的最大得分。因为是先手行动,所以先手最终能够获得的得分为这两种情况中的较大值。
  • 当前轮到后手操作,后手只能在剩余的石头中选择一个最优的石头让先手取走,并计算自己的得分。即后手能够获得的最大得分为sumLR - stones[i] + dps[L+1][R]或sumLR - stones[j] + dps[L][R-1]中的较大值。

最终,返回dpf[0][n-1] - dps[0][n-1]的绝对值,即Alice和Bob得分的差值。

时间复杂度为$O(n2)$,空间复杂度为$O(n2)$,其中n是石头的数量。

计算dpf和dps数组的过程需要遍历所有的状态,其中每个状态需要O(1)的时间进行计算,因此总时间复杂度为$O(n2)$。另外,因为需要维护两个二维数组,所以需要O(n2)的额外空间来存储这些状态。

3.另一种尝试

该函数使用动态规划实现了石子游戏。定义dp[len][i]表示从第i块石头出发,当长度为len时,Alice能比Bob多多少分?其中所谓的长度为len是指剩下的石头数量。例如,假设当前还剩下5块石头,即len=5,则dp[5][i]表示从第i块石头出发,当只剩下5块石头时,Alice能比Bob多多少分。

首先,如果剩余的石头数量为偶数,那么Alice一定会选择先手,并且每次都取走价值最高的石头。因此,对于所有的i,dp[1][i]都等于stones[i]。对于剩余的情况,我们需要使用动态规划来计算dp[len][i]。具体来说,我们可以考虑当前轮到先手操作,他可以选择拿走第i块石头或第j块石头,然后根据后续状态递归计算。

因为状态之间存在依赖关系,所以我们可以倒序遍历数组,从右下角开始计算。具体来说,我们可以按照如下方式进行状态转移:

  • 如果当前是先手操作,那么他可以选择拿走第i块石头或第j块石头。如果他选择了第i块石头,那么剩下的石头数量就变成了len-1,并且下一个人变成了后手,此时当前状态的价值为stones[i]-dp[len-1][i+1];如果他选择了第j块石头,那么剩下的石头数量也变成了len-1,但是下一个人仍然是后手,此时当前状态的价值为stones[j]-dp[len-1][i]。因为是先手行动,所以他会选择让自己的得分更高,即dp[len][i]=max(stones[i]-dp[len-1][i+1], stones[j]-dp[len-1][i])。
  • 如果当前是后手操作,那么他只能在剩余的石头中选择一个最优的石头让先手取走,并计算自己的得分。具体来说,如果他选择了第i块石头,那么剩余的石头数量就变成了len-1,并且下一个人变成了先手,此时当前状态的价值为-dp[len-1][i+1];如果他选择了第j块石头,那么剩余的石头数量也变成了len-1,但是下一个人仍然是先手,此时当前状态的价值为-dp[len-1][i]。因为是后手行动,所以他会选择让自己的得分更高,即dp[len][i]=min(-dp[len-1][i+1], -dp[len-1][i])。

最终,我们返回dp[0][n-1]的值,即从第0块石头出发,当长度为n时,Alice能比Bob多多少分。

时间复杂度为$O(n2)$,空间复杂度为$O(n2)$,其中n是石头的数量。

计算dp数组的过程需要遍历所有的状态,其中每个状态需要O(1)的时间进行计算,因此总时间复杂度为$O(n2)$。另外,由于需要维护一个二维数组,所以需要$O(n2)$的额外空间来存储这些状态。

三种算法总结

综上所述,第二种和第三种方法的时间复杂度和空间复杂度相同,都比第一种方法更加高效。在实际使用中,我们应该优先选择动态规划算法来解决这类问题,因为它能够在多项式时间内求解,而递归算法则往往会导致指数级别的复杂度。

go完整代码如下:

package main

import (
"fmt"
) // 递归版
func stoneGameVII1(stones []int) int {
sum := 0
for _, num := range stones {
sum += num
}
alice := f(stones, sum, 0, len(stones)-1)
bob := s(stones, sum, 0, len(stones)-1)
return abs(alice - bob)
} // 先手
func f(stones []int, sum, L, R int) int {
if L == R { // 只能一块儿了!
return 0
} // L为起点
p1 := sum - stones[L] + s(stones, sum-stones[L], L+1, R)
against1 := f(stones, sum-stones[L], L+1, R) // R为终点
p2 := sum - stones[R] + s(stones, sum-stones[R], L, R-1)
against2 := f(stones, sum-stones[R], L, R-1) if p1-against1 > p2-against2 {
return p1
}
return p2
} // 后手!
func s(stones []int, sum, L, R int) int {
if L == R {
return 0
} // 当前的是后手
// 对手,先手!
against1 := sum - stones[L] + s(stones, sum-stones[L], L+1, R)
// 当前用户的得分!后手!是对手决定的!
get1 := f(stones, sum-stones[L], L+1, R) against2 := sum - stones[R] + s(stones, sum-stones[R], L, R-1)
get2 := f(stones, sum-stones[R], L, R-1) if against1-get1 > against2-get2 {
return get1
}
return get2
} // 动态规划版
func stoneGameVII2(stones []int) int {
n := len(stones)
presum := make([]int, n+1)
for i := 0; i < n; i++ {
presum[i+1] = presum[i] + stones[i]
}
dpf := make([][]int, n)
dps := make([][]int, n)
for i := range dpf {
dpf[i] = make([]int, n)
dps[i] = make([]int, n)
} for L := n - 2; L >= 0; L-- {
for R := L + 1; R < n; R++ {
sumLR := presum[R+1] - presum[L]
a := sumLR - stones[L] + dps[L+1][R]
b := dpf[L+1][R]
c := sumLR - stones[R] + dps[L][R-1]
d := dpf[L][R-1]
if a-b > c-d {
dpf[L][R] = a
dps[L][R] = b
} else {
dpf[L][R] = c
dps[L][R] = d
}
}
}
return abs(dpf[0][n-1] - dps[0][n-1])
} // 另一种尝试 + static动态规划表 + 空间压缩 + 尽量优化
// dp[len][i] : 从i出发,当长度为len的情况下,Alice能比Bob多多少分?
// 要注意结算时机!这是这种尝试的核心!
var dp [1000]int // 时间复杂度和刚才讲的一样!
func stoneGameVII3(stones []int) int {
n := len(stones)
for i := 0; i < n; i++ {
dp[i] = 0
} if n%2 == 0 {
for i := 0; i < n; i++ {
dp[i] = stones[i]
}
} alicePick := n%2 == 0
for len := 2; len <= n; len, alicePick = len+1, !alicePick {
for i, j := 0, len-1; j < n; i, j = i+1, j+1 {
if alicePick {
dp[i] = max(dp[i], dp[i+1])
} else {
dp[i] = min(dp[i]+stones[j], stones[i]+dp[i+1])
}
}
}
return dp[0]
} func abs(a int) int {
if a < 0 {
return -a
}
return a
} func max(a, b int) int {
if a > b {
return a
}
return b
} func min(a, b int) int {
if a < b {
return a
}
return b
} func main() {
stones := []int{5, 3, 1, 4, 2}
fmt.Println(stoneGameVII1(stones))
fmt.Println(stoneGameVII2(stones))
fmt.Println(stoneGameVII3(stones))
}

rust完整代码如下:

fn main() {
let stones = vec![5, 3, 1, 4, 2];
let result = stone_game_vii1(stones);
println!("{}", result); let stones = vec![5, 3, 1, 4, 2];
let result = stone_game_vii2(stones);
println!("{}", result); let stones = vec![5, 3, 1, 4, 2];
let result = stone_game_vii3(stones);
println!("{}", result);
} fn stone_game_vii1(stones: Vec<i32>) -> i32 {
let sum: i32 = stones.iter().sum();
let alice = f(&stones, sum, 0, stones.len() - 1);
let bob = s(&stones, sum, 0, stones.len() - 1);
(alice - bob).abs()
} // 先手
fn f(stones: &Vec<i32>, sum: i32, l: usize, r: usize) -> i32 {
if l == r {
return 0;
} // p1
let p1 = sum - stones[l] + s(stones, sum - stones[l], l + 1, r);
let against1 = f(stones, sum - stones[l], l + 1, r); // p2
let p2 = sum - stones[r] + s(stones, sum - stones[r], l, r - 1);
let against2 = f(stones, sum - stones[r], l, r - 1); if p1 - against1 > p2 - against2 {
p1
} else {
p2
}
} // 后手
fn s(stones: &Vec<i32>, sum: i32, l: usize, r: usize) -> i32 {
if l == r {
return 0;
} let against1 = sum - stones[l] + s(stones, sum - stones[l], l + 1, r);
let get1 = f(stones, sum - stones[l], l + 1, r); let against2 = sum - stones[r] + s(stones, sum - stones[r], l, r - 1);
let get2 = f(stones, sum - stones[r], l, r - 1); if against1 - get1 > against2 - get2 {
get1
} else {
get2
}
} fn stone_game_vii2(stones: Vec<i32>) -> i32 {
let n = stones.len();
let mut presum = vec![0; n + 1];
for i in 0..n {
presum[i + 1] = presum[i] + stones[i];
} let mut dpf = vec![vec![0; n]; n];
let mut dps = vec![vec![0; n]; n]; for l in (0..n - 1).rev() {
for r in l + 1..n {
let sum_lr = presum[r + 1] - presum[l];
let a = sum_lr - stones[l] + dps[l + 1][r];
let b = dpf[l + 1][r];
let c = sum_lr - stones[r] + dps[l][r - 1];
let d = dpf[l][r - 1];
dpf[l][r] = if a - b > c - d { a } else { c };
dps[l][r] = if a - b > c - d { b } else { d };
}
} (dpf[0][n - 1] - dps[0][n - 1]).abs()
} fn stone_game_vii3(stones: Vec<i32>) -> i32 {
let n = stones.len();
let mut dp = unsafe { DP };
dp.iter_mut().take(n).for_each(|x| *x = 0); if n % 2 == 0 {
for i in 0..n {
dp[i] = stones[i];
}
} let mut alice_pick = n % 2 == 0;
for len in 2..=n {
for i in 0..=(n - len) {
let j = i + len - 1;
dp[i] = if alice_pick {
dp[i].max(dp[i + 1])
} else {
(dp[i] + stones[j]).min(stones[i] + dp[i + 1])
};
}
alice_pick = !alice_pick;
} dp[0]
} static mut DP: [i32; 1000] = [0; 1000];

c完整代码如下:

#include <stdio.h>
#include <stdlib.h> int f(int* stones, int sum, int L, int R);
int s(int* stones, int sum, int L, int R); int stoneGameVII1(int* stones, int stonesSize) {
int sum = 0;
for (int i = 0; i < stonesSize; i++) {
sum += stones[i];
}
int alice = f(stones, sum, 0, stonesSize - 1);
int bob = s(stones, sum, 0, stonesSize - 1);
return abs(alice - bob);
} // 先手
int f(int* stones, int sum, int L, int R) {
if (L == R) { // 只能一块儿了!
return 0;
} // L为起点
int p1 = sum - stones[L] + s(stones, sum - stones[L], L + 1, R);
int against1 = f(stones, sum - stones[L], L + 1, R); // R为终点
int p2 = sum - stones[R] + s(stones, sum - stones[R], L, R - 1);
int against2 = f(stones, sum - stones[R], L, R - 1); if (p1 - against1 > p2 - against2) {
return p1;
}
return p2;
} // 后手
int s(int* stones, int sum, int L, int R) {
if (L == R) {
return 0;
} // 当前的是后手
// 对手,先手!
int against1 = sum - stones[L] + s(stones, sum - stones[L], L + 1, R);
// 当前用户的得分!后手!是对手决定的!
int get1 = f(stones, sum - stones[L], L + 1, R); int against2 = sum - stones[R] + s(stones, sum - stones[R], L, R - 1);
int get2 = f(stones, sum - stones[R], L, R - 1); if (against1 - get1 > against2 - get2) {
return get1;
}
return get2;
} int stoneGameVII2(int* stones, int stonesSize) {
int N = stonesSize;
int** dpf = (int**)malloc(N * sizeof(int*));
int** dps = (int**)malloc(N * sizeof(int*));
for (int i = 0; i < N; i++) {
dpf[i] = (int*)malloc(N * sizeof(int));
dps[i] = (int*)malloc(N * sizeof(int));
memset(dpf[i], 0, N * sizeof(int));
memset(dps[i], 0, N * sizeof(int));
}
int* presum = (int*)malloc((N + 1) * sizeof(int));
memset(presum, 0, (N + 1) * sizeof(int));
for (int i = 0; i < N; i++) {
presum[i + 1] = presum[i] + stones[i];
}
for (int L = N - 2; L >= 0; L--) {
for (int R = L + 1; R < N; R++) {
int sumLR = presum[R + 1] - presum[L];
int a = sumLR - stones[L] + dps[L + 1][R];
int b = dpf[L + 1][R];
int c = sumLR - stones[R] + dps[L][R - 1];
int d = dpf[L][R - 1];
dpf[L][R] = (a - b > c - d) ? a - b : c - d;
dps[L][R] = (b > d) ? b : d;
}
}
int result = abs(dpf[0][N - 1] - dps[0][N - 1]);
for (int i = 0; i < N; i++) {
free(dpf[i]);
free(dps[i]);
}
free(presum);
free(dpf);
free(dps);
return result;
} int dp[1001]; int stoneGameVII3(int* stones, int stonesSize) {
int n = stonesSize;
memset(dp, 0, sizeof(dp));
if (n % 2 == 0) {
for (int i = 0; i < n; i++) {
dp[i] = stones[i];
}
}
int alicePick = n % 2 == 0 ? 1 : 0;
for (int len = 2; len <= n; len++, alicePick = !alicePick) {
for (int i = 0, j = len - 1; j < n; i++, j++) {
if (alicePick) {
dp[i] = dp[i] > dp[i + 1] ? dp[i] : dp[i + 1];
}
else {
int a = dp[i] + stones[j];
int b = stones[i] + dp[i + 1];
dp[i] = a < b ? a : b;
}
}
}
return dp[0];
} int main() {
int stones[] = { 5, 3, 1, 4, 2 };
int stonesSize = sizeof(stones) / sizeof(int);
printf("stoneGameVII1: %d\n", stoneGameVII1(stones, stonesSize));
printf("stoneGameVII2: %d\n", stoneGameVII2(stones, stonesSize));
printf("stoneGameVII3: %d\n", stoneGameVII3(stones, stonesSize));
return 0;
}

c++完整代码如下:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring> using namespace std; int f(vector<int>& stones, int sum, int L, int R);
int s(vector<int>& stones, int sum, int L, int R); int stoneGameVII1(vector<int>& stones) {
int sum = 0;
for (int num : stones) {
sum += num;
}
int alice = f(stones, sum, 0, stones.size() - 1);
int bob = s(stones, sum, 0, stones.size() - 1);
return abs(alice - bob);
} // 先手
int f(vector<int>& stones, int sum, int L, int R) {
if (L == R) { // 只能一块儿了!
return 0;
} // L为起点
int p1 = sum - stones[L] + s(stones, sum - stones[L], L + 1, R);
int against1 = f(stones, sum - stones[L], L + 1, R); // R为终点
int p2 = sum - stones[R] + s(stones, sum - stones[R], L, R - 1);
int against2 = f(stones, sum - stones[R], L, R - 1); if (p1 - against1 > p2 - against2) {
return p1;
}
return p2;
} // 后手!
int s(vector<int>& stones, int sum, int L, int R) {
if (L == R) {
return 0;
} // 当前的是后手
// 对手,先手!
int against1 = sum - stones[L] + s(stones, sum - stones[L], L + 1, R);
// 当前用户的得分!后手!是对手决定的!
int get1 = f(stones, sum - stones[L], L + 1, R); int against2 = sum - stones[R] + s(stones, sum - stones[R], L, R - 1);
int get2 = f(stones, sum - stones[R], L, R - 1); if (against1 - get1 > against2 - get2) {
return get1;
}
return get2;
} // 动态规划版
int stoneGameVII2(vector<int>& stones) {
int N = stones.size();
vector<vector<int>> dpf(N, vector<int>(N, 0));
vector<vector<int>> dps(N, vector<int>(N, 0));
vector<int> presum(N + 1, 0);
for (int i = 0; i < N; i++) {
presum[i + 1] = presum[i] + stones[i];
}
for (int L = N - 2; L >= 0; L--) {
for (int R = L + 1; R < N; R++) {
int sumLR = presum[R + 1] - presum[L];
int a = sumLR - stones[L] + dps[L + 1][R];
int b = dpf[L + 1][R];
int c = sumLR - stones[R] + dps[L][R - 1];
int d = dpf[L][R - 1];
dpf[L][R] = max(a - b, c - d);
dps[L][R] = max(b, d);
}
}
return abs(dpf[0][N - 1] - dps[0][N - 1]);
} // 另一种尝试 + static动态规划表 + 空间压缩 + 尽量优化
// dp[len][i] : 从i出发,当长度为len的情况下,Alice能比Bob多多少分?
// 要注意结算时机!这是这种尝试的核心!
int dp[1001]; // 时间复杂度和刚才讲的一样!
int stoneGameVII3(vector<int>& s) {
int n = s.size();
memset(dp, 0, sizeof(dp));
if (n % 2 == 0) {
for (int i = 0; i < n; i++) {
dp[i] = s[i];
}
}
bool alicePick = n % 2 == 0;
for (int len = 2; len <= n; len++, alicePick = !alicePick) {
for (int i = 0, j = len - 1; j < n; i++, j++) {
dp[i] = alicePick ? max(dp[i], dp[i + 1]) : min(dp[i] + s[j], s[i] + dp[i + 1]);
}
}
return dp[0];
} int main() {
vector<int> stones = { 5, 3, 1, 4, 2 };
cout << "stoneGameVII1: " << stoneGameVII1(stones) << endl;
cout << "stoneGameVII2: " << stoneGameVII2(stones) << endl;
cout << "stoneGameVII3: " << stoneGameVII3(stones) << endl;
return 0;
}

2023-05-09:石子游戏中,爱丽丝和鲍勃轮流进行自己的回合,爱丽丝先开始 。 有 n 块石子排成一排。 每个玩家的回合中,可以从行中 移除 最左边的石头或最右边的石头, 并获得与该行中剩余石头值的更多相关文章

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

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

  2. poj1067-取石子游戏 (威佐夫博弈)

    http://poj.org/problem?id=1067 取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36 ...

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

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

  4. 【BZOJ】【1115】【POI2009】石子游戏KAM

    博弈论 这个题……一看就觉得很捉急啊= =肿么办? 灵光一现:差分一下~ 那么我们看一下差分以后,从第 i 堆中拿走 k 个石子变成了:a[i]-=k; a[i+1]+=k; 嗯这就转化成了阶梯博弈! ...

  5. vijos 1557:bzoj:1413: [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  6. [BZOJ1115][POI2009]石子游戏Kam解题报告|阶梯博弈

    有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数.两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏.问先手是否必胜. 首先 ...

  7. bzoj 1115: [POI2009]石子游戏Kam -- 博弈论

    1115: [POI2009]石子游戏Kam Time Limit: 10 Sec  Memory Limit: 162 MB Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前 ...

  8. BZOJ 1115 [POI2009]石子游戏Kam(阶梯博弈)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1115 [题目大意] 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数. ...

  9. 【BZOJ1413】取石子游戏(博弈,区间DP)

    题意:在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从最左或最右的一堆中 ...

  10. 【BZOJ1115】[POI2009]石子游戏Kam 阶梯博弈

    [BZOJ1115][POI2009]石子游戏Kam Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数.两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要 ...

随机推荐

  1. nginx 代理路径

    反向代理被代理url没有截取 /report/api/ /report/api/bussinessRisk/zhucai/creditInquiry 应该是/bussinessRisk/zhucai/ ...

  2. 华大单片机HC32L13X软件设计时候要注意的事项

    1.系统启动时默认设置主频为内部4MHz; 2.调试超低功耗程序或者把SWD端口复用为GPIO功能都会把芯片的SWD功能关掉,仿真器将会与芯片失去连接,建议在main函数开始后加上1到2秒的延时,仿真 ...

  3. 7. 基础增删改 - 创建管理员用Model-Drive App管理后台信息 - 在Model-Driven App中创建视图

    ​ 当我们创建完Model-Driven之后,就可以在里面创建我们所需要的视图,视图一般分为三类: 个人:根据自己的个人需求创建个人视图,只有创建者和其分享的人才能查看这些视图. 公共:可以根据团体需 ...

  4. linux sed 编辑

    只打印不修改内容 sed -n 's/sa/sa123/g' 1.txt  不加n是默认全部输出的意思 sed -n '1p' 1.txt  打印莫一行 sed a i c 表示追加 插入和替换 se ...

  5. 68.C++中的const

      编写程序过程中,我们有时不希望改变某个变量的值.此时就可以使用关键字 const 对变量的类型加以限定. 初始化和const   因为const对象一旦创建后其值就不能再改变,所以const对象必 ...

  6. Windows xp 64 bit

    Windows XP Professional x64 Edition with SP2 - VL (English) 详细信息 文件名 en_win_xp_pro_x64_with_sp2_vl_X ...

  7. springboot 接入 ChatGPT

    项目地址 https://gitee.com/Kindear/lucy-chat 介绍 lucy-chat是接入OpenAI-ChatGPT大模型人工智能的Java解决方案,大模型人工智能的发展是不可 ...

  8. 基于VirutalBox搭建虚拟机间互通的可访问公网的mini主机群

    目标 在单台PC机上安装3+台虚拟机[1] 这些虚拟机间可以相互访问 宿主机[2]与虚拟机可以相互访问 虚拟机可以访问公网 本文将采用 NAT + Host-Only 双网卡的方式实现上述目标,因为采 ...

  9. redis.clients.jedis.exceptions.JedisConnectionException: Failed connecting to "xxxxx"

    Java 连接 Redis所遇问题 1. 检查Linux是否关闭防火墙,或对外开放redis默认端口6379 关闭防火墙. systemctl stop firewalld 对外开放端口.firewa ...

  10. 全局唯一ID的实现方案

    为什么需要保证唯一ID? 在单机服务架构中,数据库的每一个业务表的主键ID都是允许自增的,但是在分布式服务架构的分库分表的设计,使得多个库或者多个表存储了相同的业务表,如果没有一个全局的唯一ID设计方 ...