【算法】【递归与动态规划模块】纸牌博弈问题(多线路型递归)
admin
2024-01-22 13:04:58
0

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定数组arr,现在有两个人A和B,分别从arr的头或者尾轮流取数字,并各自将取到的数组进行累加,直到arr数组被取完为止,A和B的数字累加和大的一方为胜出方,求胜出方获得的分数。

解决方案

原问题
递归方法:
1、首先设计两个递归函数,分别为first和second,first函数入参:arr、left、right,代表arr[left…right]数组在先选的情况下获胜者的分数是多少。second函数入参:arr、left、right,代表arr[left…right]在后选择的情况下获胜者的分数是多少。
2、first表示先选,那么可以选择任何一边,选完之后自己就变成了第二个选择的人了,自己想要获胜就要返回 arr[left+1…right]和arr[left…right-1] 在第二个选择的情况下的最大值。
3、second表示第二个选,那么当前就变成第一个选了,也就是arr[left+1…right]和arr[left…right-1] 在第一个选择情况下的最大值。
详情见代码
动态规划:
通过递归可以提取出两个dp,分别代表第一个选择情况下获胜的分数和第二个选择下获胜的分数。
详情见代码

代码编写

java语言版本

原问题:
经典递归版本:

    /*** 二轮测试:递归方法* @param arr* @return*/public static int winCp1(int[] arr) {if (arr == null || arr.length == 0) {return 0;}// 对a来说是先走,对b来说是后走,取最大的return Math.max(first(arr, 0, arr.length-1), second(arr, 0, arr.length - 1)) ;}/*** 先选的人最终获得的分数* @param arr* @param left* @param right* @return*/private static int first(int[] arr, int left, int right) {if (left == right) {return arr[left];}return Math.max(arr[left] + second(arr, left+1, right), arr[right] + second(arr, left, right-1));}/*** 后选的人最终获得的分数* @param arr* @param left* @param right* @return*/private static int second(int[] arr, int left, int right) {if (left == right) {// 第二个选就么得选return 0;}return Math.min(first(arr, left+1, right), first(arr, left, right-1));}

经典动态规划版本:

    /*** 二轮测试:动态规划方法* @param arr* @return*/public static int dpCp1(int[] arr) {if (arr == null || arr.length == 0) {return 0;}// 先选dpint[][] firstDp = new int[arr.length][arr.length];// 后选dpint[][] secondDp = new int[arr.length][arr.length];// 初始化for (int i = 0; i < arr.length; i++) {firstDp[i][i] = arr[i];secondDp[i][i] = 0;}for (int j = 1; j < arr.length; j++) {for (int i = j-1; i >= 0; i--) {firstDp[i][j] = Math.max(arr[i] + secondDp[i+1][j], arr[j] + secondDp[i][j-1]);secondDp[i][j] = Math.min(firstDp[i+1][j], firstDp[i][j-1]);}}return Math.max(firstDp[0][arr.length-1], secondDp[0][arr.length-1]);}

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

参考:https://swzhao.blog.csdn.net/article/details/127854150

这道题和“参考”这道题有一点点的相似之处,毕竟两道题都是两个dp并且dp的填充方式都差不多,所以我就比较好奇这是一种什么题型,首先我们把这道题两个递归的方式合并为一个递归的方式可以吗?肯定是可以的。只不过多一个参数代表 “第几个选”,然后根据参数进行判断,由此将两个递归可以合并成一个递归,如果你真的动手合并了一下那么应该也会觉得“参考”的递归代码结构体和这道题的非常相似,但是参考代码结构的那个是目标值aim,这里的是第一个选还是第二个选。我们发现这个入参可以将我们的递归分为两种不同的路线走下去,并不是传统的递归只有一条状态之间的递归线,前面我们做的题目都是传统的当前状态依赖前面的状态这种单一路线型逻辑,这句话不知道合不合适,我就命名为单一路线型递归问题。而参考题型和当前题型都算是多路线型递归,也就是说当前状态不完全的依赖前面的所有状态,而是会根据 一个标志性判断走不通的路线。这种题型需要在设计递归的时候增加这个标志而这个标志也是最难设计的,不过这个标志有一个特点,那就是范围绝对不会太大。比如aim只有两个状态true和false,当前题目只有两个状态:第一个选、第二个选。

这里拓展一下,如果三个人玩这个游戏呢?四个人呢?n个人呢?
如果你看懂了上面的解释,那么拓展多少人都可以,只不过那个标志性判断的范围就是 第一个选、第二个选、第三个选、第n个选。。。。

同时参考题目也可以变成 目标为 aim1的组合、目标为aim2的组合、目标为aim3的组合。。。千篇一律~

如果有朋友知道这种题型的专业术语请及时纠正哈~

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

相关内容

热门资讯

V观财报|5天3板百利科技:日... 【V观财报|5天3板百利科技:日常经营情况未发生重大变化】5天3板百利科技公告,经公司自查,公司目前...
宁波银行好猛!但个贷不良率涨的... 要说上半年最春风得意的城商行,一定有宁波银行的一席之地。不仅实现了营收、利润的双增长;更超越上海银行...
半年盘点|上半年增收不增利但价... 在136号文新能源抢装潮下,风电行业迎来“出货大年”。上半年全国风电累计装机容量超5.7亿千瓦,同比...
V观财报|爱柯迪副总经理张恂杰... 【V观财报|爱柯迪副总经理张恂杰辞职】爱柯迪公告,公司董事会于近日收到公司副总经理张恂杰递交的书面辞...
活力中国调研行|百年外资行要做... 渣打银行大楼受访者供图扎根中国160余年,业务从未间断;亲历中国金融市场诸多里程碑式开放,深度参与“...
罗永浩:决定放弃进一步追究西贝 中新网9月15日电 9月15日,罗永浩在微博发文表示,决定放弃进一步追究西贝。 图自@罗永浩的十字...
剑南春集团新增国资为第二大股东... 微成都报道天眼查最新显示,9月12日,四川剑南春(集团)有限责任公司发生工商变更,新增绵竹市国有资产...
上市公司协会通报典型,8个案例... 9月15日,中国上市公司协会发布《涉上市公司虚假新闻和新闻敲诈典型案例》,将2024—2025年间收...
预制菜国标或将出台,多只概念股... 近日,随着罗永浩称西贝“几乎全是预制菜”事件不断发酵,预制菜也得到了广泛关注。9月13日,有媒体报道...
西贝不懂公关?罗永浩必败无疑?... *此图由AI生成作者| 史大郎&猫哥来源| 是史大郎&大猫财经Pro罗永浩和西贝的争端,想停都停不下...