Python每日一练(20230510) 石子游戏 VII\VIII\IX

简介: Python每日一练(20230510) 石子游戏 VII\VIII\IX

1. 石子游戏 Stone Game VII


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


有 n 块石子排成一排。每个玩家的回合中,可以从行中 移除 最左边的石头或最右边的石头,并获得与该行中剩余石头值之 和 相等的得分。当没有石头可移除时,得分较高者获胜。


鲍勃发现他总是输掉游戏(可怜的鲍勃,他总是输),所以他决定尽力 减小得分的差值 。爱丽丝的目标是最大限度地 扩大得分的差值 。


给你一个整数数组 stones ,其中 stones[i] 表示 从左边开始 的第 i 个石头的值,如果爱丽丝和鲍勃都 发挥出最佳水平 ,请返回他们 得分的差值 。


示例 1:

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

输出:6


解释:

- 爱丽丝移除 2 ,得分 5 + 3 + 1 + 4 = 13 。游戏情况:爱丽丝 = 13 ,鲍勃 = 0 ,石子 = [5,3,1,4] 。

- 鲍勃移除 5 ,得分 3 + 1 + 4 = 8 。游戏情况:爱丽丝 = 13 ,鲍勃 = 8 ,石子 = [3,1,4] 。

- 爱丽丝移除 3 ,得分 1 + 4 = 5 。游戏情况:爱丽丝 = 18 ,鲍勃 = 8 ,石子 = [1,4] 。

- 鲍勃移除 1 ,得分 4 。游戏情况:爱丽丝 = 18 ,鲍勃 = 12 ,石子 = [4] 。

- 爱丽丝移除 4 ,得分 0 。游戏情况:爱丽丝 = 18 ,鲍勃 = 12 ,石子 = [] 。

得分的差值 18 - 12 = 6 。


示例 2:

输入:stones = [7,90,5,1,100,10,10,2]

输出:122


提示:

   n == stones.length

   2 <= n <= 1000

   1 <= stones[i] <= 1000


代码1: 动态规划


from typing import List
class Solution:
    def stoneGameVII(self, stones: List[int]) -> int:
        n = len(stones)
        dp = [[0] * n for _ in range(n)]
        prefix_sum = [0] * (n + 1)
        for i in range(n):
            prefix_sum[i + 1] = prefix_sum[i] + stones[i]
        for length in range(2, n + 1):
            for i in range(n - length + 1):
                j = i + length - 1
                dp[i][j] = max(prefix_sum[j + 1] - prefix_sum[i + 1] - dp[i + 1][j], 
                               prefix_sum[j] - prefix_sum[i] - dp[i][j - 1])
        return dp[0][n - 1]
#%%
s = Solution()
stones = [5,3,1,4,2]
print(s.stoneGameVII(stones))
stones = [7,90,5,1,100,10,10,2]
print(s.stoneGameVII(stones))


代码2:记忆化搜索

from typing import List
class Solution:
    def stoneGameVII(self, stones: List[int]) -> int:
        n = len(stones)
        prefix_sum = [0] * (n + 1)
        for i in range(n):
            prefix_sum[i + 1] = prefix_sum[i] + stones[i]
        memo = [[None] * n for _ in range(n)]
        def dfs(left, right):
            if left == right:
                return 0
            if memo[left][right] is not None:
                return memo[left][right]
            res = max(prefix_sum[right + 1] - prefix_sum[left + 1] - dfs(left + 1, right), 
                      prefix_sum[right] - prefix_sum[left] - dfs(left, right - 1))
            memo[left][right] = res
            return res
        return dfs(0, n - 1)
#%%
s = Solution()
stones = [5,3,1,4,2]
print(s.stoneGameVII(stones))
stones = [7,90,5,1,100,10,10,2]
print(s.stoneGameVII(stones))


输出:

6

122



2. 石子游戏 Stone Game VIII


Alice 和 Bob 玩一个游戏,两人轮流操作, Alice 先手


总共有 n 个石子排成一行。轮到某个玩家的回合时,如果石子的数目 大于 1 ,他将执行以下操作:


   选择一个整数 x > 1 ,并且 移除 最左边的 x 个石子。

   将 移除 的石子价值之 和 累加到该玩家的分数中。

   将一个 新的石子 放在最左边,且新石子的值为被移除石子值之和。


当只剩下 一个 石子时,游戏结束。


Alice 和 Bob 的 分数之差 为 (Alice 的分数 - Bob 的分数) 。 Alice 的目标是 最大化 分数差,Bob 的目标是 最小化 分数差。


给你一个长度为 n 的整数数组 stones ,其中 stones[i] 是 从左边起 第 i 个石子的价值。请你返回在双方都采用 最优 策略的情况下,Alice 和 Bob 的 分数之差 。


示例 1:

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

输出:5


解释:

- Alice 移除最左边的 4 个石子,得分增加 (-1) + 2 + (-3) + 4 = 2 ,并且将一个价值为 2 的石子放在最左边。stones = [2,-5] 。

- Bob 移除最左边的 2 个石子,得分增加 2 + (-5) = -3 ,并且将一个价值为 -3 的石子放在最左边。stones = [-3] 。

两者分数之差为 2 - (-3) = 5 。


示例 2:

输入:stones = [7,-6,5,10,5,-2,-6]

输出:13


解释:

- Alice 移除所有石子,得分增加 7 + (-6) + 5 + 10 + 5 + (-2) + (-6) = 13 ,并且将一个价值为 13 的石子放在最左边。stones = [13] 。

两者分数之差为 13 - 0 = 13 。


示例 3:

输入:stones = [-10,-12]

输出:-22


解释:

- Alice 只有一种操作,就是移除所有石子。得分增加 (-10) + (-12) = -22 ,并且将一个价值为 -22 的石子放在最左边。stones = [-22] 。

两者分数之差为 (-22) - 0 = -22 。


提示:

   n == stones.length

   2 <= n <= 10^5

   -10^4 <= stones[i] <= 10^4


代码: 动态规划

from typing import List
class Solution:
    def stoneGameVIII(self, stones: List[int]) -> int:
        n = len(stones)
        prefix_sum = [0] * (n + 1)
        for i in range(n):
            prefix_sum[i + 1] = prefix_sum[i] + stones[i]
        dp = [0] * n
        dp[n - 1] = prefix_sum[n]
        for i in range(n - 2, 0, -1):
            dp[i] = max(dp[i + 1], prefix_sum[i + 1] - dp[i + 1])
        return dp[1]
#%%
s = Solution()
stones = [-1,2,-3,4,-5]
print(s.stoneGameVIII(stones))
stones = [7,-6,5,10,5,-2,-6]
print(s.stoneGameVIII(stones))
stones = [-10,-12]
print(s.stoneGameVIII(stones))



输出:

5

13

-22


3. 石子游戏 Stone Game IX


Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。


Alice 和 Bob 轮流进行自己的回合,Alice 先手。每一回合,玩家需要从 stones 中移除任一石子。


   如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。


   如果不满足上一条,且移除后没有任何剩余的石子,那么 Bob 将会直接获胜(即便是在 Alice 的回合)。


假设两位玩家均采用 最佳 决策。如果 Alice 获胜,返回 true ;如果 Bob 获胜,返回 false 。


示例 1:

输入:stones = [2,1]

输出:true


解释:游戏进行如下:

- 回合 1:Alice 可以移除任意一个石子。

- 回合 2:Bob 移除剩下的石子。  

已移除的石子的值总和为 1 + 2 = 3 且可以被 3 整除。因此,Bob 输,Alice 获胜。


示例 2:

输入:stones = [2]

输出:false

解释:Alice 会移除唯一一个石子,已移除石子的值总和为 2 。  

由于所有石子都已移除,且值总和无法被 3 整除,Bob 获胜。


示例 3:

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

输出:false


解释:Bob 总会获胜。其中一种可能的游戏进行方式如下:


- 回合 1:Alice 可以移除值为 1 的第 2 个石子。已移除石子值总和为 1 。

- 回合 2:Bob 可以移除值为 3 的第 5 个石子。已移除石子值总和为 = 1 + 3 = 4 。

- 回合 3:Alices 可以移除值为 4 的第 4 个石子。已移除石子值总和为 = 1 + 3 + 4 = 8 。

- 回合 4:Bob 可以移除值为 2 的第 3 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 = 10.

- 回合 5:Alice 可以移除值为 5 的第 1 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 + 5 = 15.

Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,Bob 获胜。


提示:

   1 <= stones.length <= 10^5

   1 <= stones[i] <= 10^4


代码:

from typing import List
class Solution:
    def stoneGameIX(self, stones: List[int]) -> bool:
        count = [0] * 3  # 统计每个余数出现的次数
        for stone in stones:
            count[stone % 3] += 1
        if count[0] % 2 == 0:  # 如果余数为 0 的石子个数为偶数,Alice 一定会输
            return count[1] > 0 and count[2] > 0  # 只有同时存在余数为 1 和余数为 2 的石子,Bob 才能获胜
        return abs(count[1] - count[2]) > 2  # 如果余数为 0 的石子个数为奇数,Alice 一定会获胜
#%%
s = Solution()
stones = [2,1]
print(s.stoneGameIX(stones))
stones = [2]
print(s.stoneGameIX(stones))
stones = [5,1,2,4,3]
print(s.stoneGameIX(stones))


输出:

True

False

False

目录
相关文章
|
2月前
|
IDE 开发工具 Python
Python扑克游戏编程---摸大点
Python扑克游戏编程---摸大点
60 1
|
3月前
|
Python
python编写下象棋游戏|4-14
python编写下象棋游戏|4-14
|
3月前
|
人工智能 算法 图形学
总有一个是你想要的分享40个Python游戏源代码
这是一系列基于Python开发的游戏项目集合,包括中国象棋、麻将、足球、坦克大战、扑克等多种类型游戏,运用了Pygame等库实现图形界面与AI算法。此外还包含迷宫、数独、推箱子等益智游戏及经典游戏如《仙剑奇侠传二战棋版》和《星露谷物语》的Python版本,适合编程学习与娱乐。
124 11
|
2月前
|
数据采集 前端开发 Python
Python pygame 实现游戏 彩色 五子棋 详细注释 附源码 单机版
Python pygame 实现游戏 彩色 五子棋 详细注释 附源码 单机版
77 0
|
3月前
|
消息中间件 数据采集 数据库
庆祝吧!Python IPC让进程间的合作,比团队游戏还默契
【9月更文挑战第7天】在这个数字化时代,软件系统日益复杂,单进程已难以高效处理海量数据。Python IPC(进程间通信)技术应运而生,使多进程协作如同训练有素的电竞战队般默契。通过`multiprocessing`模块中的Pipe等功能,进程间可以直接传递数据,无需依赖低效的文件共享或数据库读写。此外,Python IPC还提供了消息队列、共享内存和套接字等多种机制,适用于不同场景,使进程间的合作更加高效、精准。这一技术革新让开发者能轻松应对复杂挑战,构建更健壮的软件系统。
39 1
|
10天前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
16天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
16天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
16天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
3天前
|
Python
Python编程入门:从零开始的代码旅程
本文是一篇针对Python编程初学者的入门指南,将介绍Python的基本语法、数据类型、控制结构以及函数等概念。文章旨在帮助读者快速掌握Python编程的基础知识,并能够编写简单的Python程序。通过本文的学习,读者将能够理解Python代码的基本结构和逻辑,为进一步深入学习打下坚实的基础。