动态规划---石子游戏

  • 石子游戏(leetcode877)
  • 石子游戏(leetcode1140)
  • 石子游戏(leetcode1686)

石子游戏(leetcode877)

题目描述
亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] 。
游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。
亚历克斯和李轮流进行,亚历克斯先开始。 每回合,玩家从行的开始或结束处取走整堆石头。 这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。
假设亚历克斯和李都发挥出最佳水平,当亚历克斯赢得比赛时返回 true ,当李赢得比赛时返回 false 。
思路

  1. 状态:游戏的得分与石子的起始和结束位置有关,选择使其位置i和结束位置j作为状态,用dp[i][j]表示以第i个石子为起始,以第j个石子为结束位置时,先手的最高得分。
  2. 状态转移方程:为了便于分析,第一个选手得分减去另一个选手得分,也即记录得分的相对值。先手有两中不同的选择:选择第i个石子,则下一个选手可得的最高分是dp[i+1][j],因此该选手的相对得分为piles[i]-dp[i+1][j];若选择第j个石子,此时同理可得该选手的得分相对值为piles[j]-dp[i][j-1]。由此可得状态转移方程为dp[i][j]=max(piles[i]-dp[i+1][j],piles[j]-dp[i][j-1])。
  3. 初始值:dp[i][i]=piles[i],因为只有一个石子。
  4. 结果:dp[0][N-1],N为石子的长度。

代码

class Solution {public:bool stoneGame(vector<int>& piles) {int N = piles.size();int dp[N][N];memset(dp, 0, sizeof(dp));for(int i = 0; i < N; i++){dp[i][i] = piles[i];  }for(int i = N-2; i >=0; i--){for(int j = i+1; j < N; j++){dp[i][j] = max(piles[i]-dp[i+1][j], piles[j]-dp[i][j-1]);}}return dp[0][N-1] > 0; }
};

石子游戏(leetcode1140)

题目描述
亚历克斯和李继续他们的石子游戏。许多堆石子 排成一行,每堆都有正整数颗石子 piles[i]。游戏以谁手中的石子最多来决出胜负。
亚历克斯和李轮流进行,亚历克斯先开始。最初,M = 1。
在每个玩家的回合中,该玩家可以拿走剩下的 前 X 堆的所有石子,其中 1 <= X <= 2M。然后,令 M = max(M, X)。
游戏一直持续到所有石子都被拿走。
假设亚历克斯和李都发挥出最佳水平,返回亚历克斯可以得到的最大数量的石头。

思路

  1. dp[i][j] 代表当前还剩下i堆石头,M为j的情况下能获取到的最大重量
  2. 状态转移方程为:
    dp[i][j] = max{sums[N] - sums[i] - dp[i - k][max(k, j)]} (1 <= k <= 2 * j)
    sums[N] - sums[i]代表剩下i堆石头的总重量,若本次取k堆,那么下次取的时候M就变成了max(k, j),
    下次能获取到的最大值对应到dp的定义就是dp[i - k][max(k, j)]

代码

class Solution {public:int stoneGameII(vector<int>& piles) {int N = piles.size();int sums[N+1];int dp[N+1][N+1];memset(sums, 0, sizeof(sums));memset(dp, 0, sizeof(dp));for(int i = 0; i < N; ++i){sums[i+1] = sums[i] + piles[i];}for(int i = 0; i <= N; ++i){for(int j = i; j <= N; j++){dp[i][j] = sums[N] - sums[N-i];   //剩余i堆石头的总和}  }for(int i = 1; i <= N; ++i){for(int j = 1; j <= N; ++j){    //剩余i堆里选k堆for(int k = 1; k <= 2*j && k <= i; ++k){dp[i][j] = max(dp[i][j], sums[N] - sums[N-i] - dp[i-k][min(max(k,j), N)]); }}}return dp[N][1];}
};

石子游戏(leetcode1686)

题目描述
Alice 和 Bob 轮流玩一个游戏,Alice 先手。
一堆石子里总共有 n 个石子,轮到某个玩家时,他可以 移出 一个石子并得到这个石子的价值。Alice 和 Bob 对石子价值有 不一样的的评判标准 。双方都知道对方的评判标准。
给你两个长度为 n 的整数数组 aliceValues 和 bobValues 。aliceValues[i] 和 bobValues[i] 分别表示 Alice 和 Bob 认为第 i 个石子的价值。
所有石子都被取完后,得分较高的人为胜者。如果两个玩家得分相同,那么为平局。两位玩家都会采用 最优策略 进行游戏。
请你推断游戏的结果,用如下的方式表示:
如果 Alice 赢,返回 1 。
如果 Bob 赢,返回 -1 。
如果游戏平局,返回 0 。
思路

  1. 贪心算法:贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题。
  2. 假设有又两个石头,Alice和Bob对这两个石头的价值分别是a1、a2、b1、b2。Alice是先手,有两种选择方案,第一种是Alice先选第一块石头,此时Alice获得的价值是a1-b2;第二种是Bob先选第一块石头,此时Alice获胜的价值是a2-b1。故两种方案的价值差为c=(a1-b2)-(a2-b1)=(a1+b1)-(a2+b2)。如果c > 0 那么方案一更优,如果c == 0,那么两种方案价值一样,如果c < 0那么方案二更优。推广得比较每个下标 i 的 a[i] + b[i] 的优劣。
  3. 贪心的策略是:合并两组石头的价值,每次取价值最大的组。Alice先取,故是奇数下标;Bob是偶数下标。

代码

class Solution {public:int stoneGameVI(vector<int>& aliceValues, vector<int>& bobValues) {int n = aliceValues.size();vector<pair<int,int>> mp;  //总和+下标for(int i = 0; i < n; ++i){int dis = aliceValues[i] + bobValues[i];mp.emplace_back(dis,i);}sort(mp.rbegin(), mp.rend()); //对价值从大到小排序int sum1 = 0, sum2 = 0;for(int i = 0; i < n; ++i){if(i % 2==0) sum1 += aliceValues[mp[i].second];else sum2 += bobValues[mp[i].second]; }if(sum1 == sum2) return 0;else if(sum1 > sum2) return 1;else return -1;}
};

动态规划---石子游戏相关推荐

  1. 【动态规划】小石子游戏-石子合并

    题目 一群小孩子在玩小石子游戏,游戏有两种玩法. (1)路边玩法 有n堆石子堆放在路边,现要将石子有序地合并成一堆,规定每次只能移动相邻的两堆石子合并,合并花费为新合成的一堆石子的数量.求将这N堆石子 ...

  2. leetcode算法题--石子游戏 II★★

    原题链接:https://leetcode-cn.com/problems/stone-game-ii/ 相关题目:石子游戏 动态规划: dp[i][j]表示在i~n-1堆石子中,最多拿前2*j堆时先 ...

  3. LeetCode 1690. 石子游戏 VII(博弈DP)

    文章目录 1. 题目 2. 解题 1. 题目 石子游戏中,爱丽丝和鲍勃轮流进行自己的回合,爱丽丝先开始 . 有 n 块石子排成一排.每个玩家的回合中,可以从行中 移除 最左边的石头或最右边的石头,并获 ...

  4. LeetCode 1686. 石子游戏 VI(贪心)

    文章目录 1. 题目 2. 解题 283 / 1660,前17% 681 / 6572,前10.4% 1. 题目 Alice 和 Bob 轮流玩一个游戏,Alice 先手. 一堆石子里总共有 n 个石 ...

  5. leetcode——石子游戏系列题目

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

  6. LeetCode-877 石子游戏

    动态规划 LeetCode-877 石子游戏 题目链接:LeetCode-877 题目大意:从一排石子堆最左面或者最右面取石子 每次一堆必须全部取走 最后石子总数多的获胜 问最后先手可不可以获胜 解题 ...

  7. BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏(SG函数)

    Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 871  Solved: 365 [Submit][Status][Discuss] Descripti ...

  8. HDUOJ-----2175取(m堆)石子游戏

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

  9. bzoj1874: [BeiJing2009 WinterCamp]取石子游戏

    1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 834  Solved: 350 ...

最新文章

  1. 看我如何下载韩寒博客文章笔记
  2. 北斗导航 | 从北一到北二再到北三,你应该知道的北斗导航系统
  3. 初学Java该学哪些知识?这6大知识必学
  4. 【BZOJ】1013 球形空间产生器
  5. 第四:RobotFramework+Allure2生成精美测试报告
  6. 从仁慈的独裁者到微软打工人,Python之父和Python将走向何方?
  7. 速修复!VMware vCenter Server 所有版本受严重的 RCE 漏洞影响
  8. 光储直流微电网能量管理。 系统主要由光伏发电模块、mppt控制模块、混合储能系统模块、直流负载模块、改进前的soc限值管理控制模块
  9. 日志清理BAT脚本带输出日志
  10. UE4 记录 UE4 中贴图
  11. java极简使用FastFDFS文件服务器上传图片
  12. .NET 开源项目概览
  13. Android产品研发(十一)--应用内跳转Scheme协议
  14. python学习四十四天(前端之HTML标签)
  15. threejs 特效 自定义发光围栏,发光墙体,闪烁动画
  16. 【可爱甜美圆嘟嘟的孩子壁纸】
  17. C语言 7-7 书号判断与纠错
  18. python中tkinter较完整的鼠标样式cursor值
  19. 杰理之TIMER【篇】
  20. VLDB 2023 | 北大河图发布分布式训练神器Galvatron,一键实现大模型高效自动并行...

热门文章

  1. 史莱姆区块查找 超简单java代码
  2. javascript如何获取html中的控件,Javascript-dom总结(获取页面控件)
  3. 华为路由器ospf路由表解读_华为路由如何建立OSPF网络详解
  4. 推荐几个程序员Mac m1max芯片笔记本软件
  5. 【视听盛宴】《高效能人士的七个习惯》分享会
  6. 世界上以一台计算机体积多大,世界上体积最大的计算机器有多大
  7. 5.1.2全景声音箱摆位_全景声音响系统,音箱应该如何摆位?(5.1.2、5.1.4篇)
  8. SemanticKITTI点云标注工具
  9. SW2016启动界面闪退、激活工具不出现All done! Enjoy!
  10. mysql和sqlite3 ios_iOS数据库存储之SQLite3