硬币游戏算法[关闭]

2023-12-21

来玩个游戏:

有 n 叠硬币排成一排。第 i 叠硬币由 d_i 个硬币组成。两名玩家:玩家 1、玩家 2 交替移动。玩家轮流只能拿走第一堆或最后一堆或两者。当没有剩余硬币时游戏结束。每个玩家都希望最终拥有尽可能多的硬币。玩家 1 开始。

我想知道算法(听起来像贪婪算法)来计算游戏结束时每个玩家在双方都发挥最佳状态时拥有多少硬币。

我不知道如何处理此类算法。只是猜测策略还是有某种方法可以推断出来?或者也许这个问题太奇怪而无法实现算法?

示例(硬币从第一个到第 n 个堆叠):

1、100、1 - 玩家分别拥有 2 和 100 个硬币(不幸的是,第一个玩家只能拿走第一堆和最后一堆 - 第二个玩家总是拿走 100 个硬币)

1, 1, 100, 1, 1, 5 - 玩家分别拥有 8 和 101 个硬币(我认为这是在最佳游戏之后 - 首先取 5 和 1,然后第二次取 1 以防止玩家 1 拿走 100 个硬币。如果玩家 1在他的第一步中拿走少于 6 个硬币,他将永远少于 8 个硬币)。

我希望我已经足够详细地说明了问题。你同意这很有趣吗? :) 有人可以帮忙吗?


添加到@Peter's动态规划解法:

我认为重现会类似于以下内容:

考虑到硬币堆的范围从A[i,..j]
Let, dp[i, j]表示玩家 1 可能获得的最高分数。然后,

dp[i, j] = MAX {
                MIN( dp[i+2, j], dp[i+1, j-1], dp[i+2, j-1]) + A[i], //Case when Player2 will try to make the most of it if Player1 picks ith coin.
                MIN( dp[i+1, j-1], dp[i, j-2], dp[i+1, j-2]) + A[j], //Case when Player2 will try to make the most of it if Player1 picks the jth coin.
                MIN( dp[i+2, j-1], dp[i+1, j-2], dp[i+2, j-2]) + A[i] + A[j] // Case when Player2 will try to make the most of it when Player1 picks both the ith and jth coins.
               }

因为只有 N^2 种可能的游戏状态。可以通过填充一个大小为N^2的dp表来实现。

对于 C++ 爱好者:

#include<iostream>
using namespace std;
int Solve(int A[], int N, int **dp, int i, int j){
        if(dp[i][j] != -1)
                return dp[i][j];
        if(j<i)
                return 0;
        else if(j==i)
                return A[i];
        else if( (j-i) == 1)
                return (A[i] + A[j]);
        else{
                int opt1 = min(Solve(A, N, dp, i+2, j), Solve(A, N, dp, i+1, j-1));
                opt1 = min(opt1, Solve(A, N, dp, i+2, j-1));
                int opt2 = min(Solve(A, N, dp, i+1, j-1), Solve(A, N, dp, i, j-2));
                opt2 = min(opt2, Solve(A, N, dp, i+1, j-2));
                int opt3 = min(Solve(A, N, dp, i+2, j-1), Solve(A, N, dp, i+1, j-2));
                opt3 = min(opt3, Solve(A, N, dp, i+2, j-2));
                int res = max(opt1+A[i], opt2+A[j]);
                res = max(res, opt3+A[i]+A[j]);
                dp[i][j] = res;
                return res;

        }
}
int main(){
        int N;
        int A[N];
        cin >> N;
        for(int i=0; i<N; ++i)
                cin >> A[i];
        int **dp;
        dp = new int* [N];
        for(int i=0; i<N; ++i)
                dp[i] = new int[N];
        for(int i=0; i<N; ++i)
                for(int j=0; j<N; ++j)
                        dp[i][j] = -1;
        Solve(A, N, dp, 0, N-1);
        cout << dp[0][N-1] << endl;
        for(int i=0; i<N; ++i)
                delete [] dp[i];
        delete []dp;
        return 0;
}

另外,如@Peter指出你对第二个例子的分析是错误的。玩家 1 实际上有一个赢得 102 个硬币来赢得比赛的策略。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

硬币游戏算法[关闭] 的相关文章

  • 优化重叠矩形的绘制

    我有很多矩形 有些与其他矩形重叠 每个矩形都有一个绝对 z 顺序和一个colour 每个 矩形 实际上是粒子效果 网格或纹理的轴对齐边界框 并且可能是半透明的 但只要您不尝试剔除其他矩形后面的矩形 就更容易抽象地思考彩色矩形 所以我将在问题
  • 布隆过滤器的使用

    我正在努力理解布隆过滤器的用处 我了解了它的底层逻辑 空间压缩 快速查找 误报等 我只是不能将这个概念应用到现实生活中 因为它是有益的 一种常见的应用是在 Web 缓存中使用布隆过滤器 我们使用布隆过滤器来确定给定的 URL 是否在缓存中
  • 比 BMH (Boyer–Moore–Horspool) 更快的算法

    您会使用哪种算法来搜索短文本中的短子字符串 简而言之 我的意思是子字符串有 5 10 个字符 字符串有 255 个字符 我正在考虑根据输入数据长度选择算法 哪种算法对于较长的输入更好 Try Turbo BM http www igm un
  • 2D形状识别与解析算法

    我正在寻找一种算法 用于从给定的一组 x y 点检测简单形状 如矩形 三角形 正方形和圆形 我还在寻找一种方法 一旦检测到 将路径转换为更干净的形状 我已经查遍了互联网 但没有找到任何 简单 的方法 几乎所有这些对于我的简单实现来说都是高级
  • 查找一个二维矩阵是否是另一个二维矩阵的子集

    最近我参加了一个黑客马拉松 我了解到一个问题 试图在 2d 矩阵中找到网格形式的模式 模式可以是 U H 和 T 并由 3 3 矩阵表示 假设我想展示 H 和 U 1 0 1 1 0 1 1 1 1 gt H 1 0 1 gt U 1 0
  • 融合元组以查找等价类

    假设我们有一个包含 k 个元素的有限域 D d1 dk 我们认为 S 是 D n 的子集 即一组 形式的元组 其中 ai 在 D 中 我们希望使用 S 2 D n 的子集 即一组 形式的元组 其中 Ai 是 D 的子集 来 紧凑地 表示它
  • 基于 2 个输入的伪随机数生成器 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我需要根据 2 个输入值 X 和 Y 生成一个伪随机数 给定相同的 X 和 Y 值 我需要得到相同的结果 结果应介于 0 和 1 之间 含
  • 寻找局部最小值

    下面的代码正确地找到了数组的局部最大值 但未能找到局部最小值 我已经进行了网络搜索 以找到找到最小值的最佳方法 并且根据这些搜索 我认为我正在使用下面的正确方法 但是 在几天的时间里多次检查每一行之后 下面的代码中有一些我仍然没有看到的错误
  • 按步长值变化对数组中的数字进行分组

    我有一个像 101 107 106 199 204 205 207 306 310 312 312 314 317 318 380 377 379 382 466 469 471 472 557 559 562 566 569 在这个数组中
  • 计算给出数组中最小标准差的子集

    让我们有一个大小的向量N 例如 x rand N 1 我想计算长度子集的最小标准差K在向量中 When N and K很小 很容易找到最好的子集 因为我可以使用nchoosek N K 枚举所有可能的子集 但是当值N and K比我们说的要
  • 整数除法性质

    下面的整数算术性质成立吗 m n l m n l 起初我以为我知道答案 不成立 但现在不确定 它适用于所有数字还是仅适用于某些条件 即n gt l 该问题涉及计算机算术 即q n m q m n 忽略溢出 Case1 assume m kn
  • 为什么我们需要检测链表中的循环

    我看到很多关于如何检测链表中的循环的问答 但我想了解的是我们为什么要这样做 换句话说 检测链表中的循环的实际用例是什么 在现实生活中 您可能永远不需要检测链表中的循环 但是执行此操作的算法很重要 我在现实生活中多次使用它们 例如 我经常会递
  • 如何使用networkx删除有向图中的所有相关节点?

    我不确定我的问题的正确术语是什么 所以我只会解释我想做的事情 我有一个有向图 删除节点后我希望所有独立相关的节点也被删除 这是一个例子 假设我删除节点 11 我希望节点 2 也被删除 在我自己的示例中 它们将是 2 以下的节点 现在也必须删
  • 随机排列

    我无法找到一种随机洗牌元素的好方法std vector经过一些操作后 恢复原来的顺序 我知道这应该是一个相当简单的算法 但我想我太累了 由于我被迫使用自定义随机数生成器类 我想我不能使用std random shuffle 无论如何这没有帮
  • 查找数组中的重叠数据

    我们正在编写一个 C 应用程序 它将有助于删除不必要的数据重复器 只有在以下情况下才可以移除中继器 all它接收到的数据被其他中继器接收 我们第一步需要做的事情解释如下 例如 我有 int 数组的集合 A 1 2 3 4 5 b 2 4 6
  • 为什么使用 no-op 来填补 paxos 事件之间的空白是合法的?

    我正在学习Paxos算法 http research microsoft com en us um people lamport pubs paxos simple pdf http research microsoft com en us
  • 计算总和等于 k ​​的子集数量

    给定一个数组 我们需要找出总和恰好等于给定整数 k 的子集的数量 请针对这个问题提出一个最佳算法 这里不需要实际的子集 只需计数即可 该数组由整数组成 可以是负数也可以是非负数 例子 数组 gt 1 4 1 10 5 绝对值总和 gt 9
  • RNG 技术的可移植性和可重复性

    我可以使用两种方法之一来创建一个伪随机数序列 该序列具有两个重要特征 1 它可以在不同的机器上重现 2 该序列永远不会重复范围内的数字 直到所有数字都被发出 我的问题是 这两种方法在可移植性 操作系统 Python 版本等 方面是否存在潜在
  • 创建将 n 个用户放入 k 个组的所有可能方法

    给定 n 个用户 u 1 u 2 u n 和 k 个组 g 1 g 2 g k 创建所有组的所有可能组合 基本上 最后每个组合都是一个Map 其中第一个Integer是用户ID 第二个Integer是组ID 例如 u 1 g 1 u 2 g
  • 模式识别算法

    过去我必须开发一个充当规则评估器的程序 你有一个先行词和一些后续词 动作 所以如果先行词评估为真 则执行的动作 当时我用的是修改版RETE算法 http en wikipedia org wiki Rete algorithm RETE 有

随机推荐