AcWing 1388. 游戏(每日一题)

原题链接:1388. 游戏 - AcWing题库

玩家一和玩家二共同玩一个小游戏。

给定一个包含 N 个正整数的序列。

由玩家一开始,双方交替行动。

每次行动可以在数列的两端之中任选一个数字将其取走,并给自己增加相应数字的分数。(双方的初始分都是 0 分)

当所有数字都被取完时,游戏结束。

分更高的一方获胜。

请计算,如果双方都采取最优策略进行游戏,则游戏结束时,双方的得分各是多少。

输入格式

第一行包含整数 N。

后面若干行包含 N 个整数,表示这个序列。注意每行不一定恰好包含一个数

输出格式

共一行,两个整数,分别表示玩家一和玩家二的最终得分。

数据范围

2≤N≤100,
数列中的数字的取值范围为 [1,200]。

输入样例:

6
4 7 2 9
5 2

输出样例:

18 11

解题思路:

又是这种决策游戏,思想上还是有博弈论的,玩家一与玩家二都绝对的聪明都具有上帝视角,既让自己获得分数最大,也让对方获得的分数尽量少,两个玩家都是最优策略,不存在一方每次拿最大的,另一方每次拿最小的,而且应该每个玩家都有上帝视角。


样例:4,7,2,9,5,2
玩家一(先手):拿两边的4或2,但是我拿了4玩家二会拿7,我拿2,玩家二要么拿4要么拿5,这样7或9我势在必得一个,于是想了想我拿2
此时样例:4,7,2,9,5
玩家二:拿4的话玩家一会拿7,我拿5的话,玩家一会拿9,9>7,还是拿4划算
此时样例:7,2,9,5
玩家一:这时候肯定拿7,拿5的话,9就被玩家二拿去了
此时样例:2,9,5
玩家二:不管拿2,5都会让9被玩家1拿走,所有拿5,尽可能保证自己更大。
此时样例:2,9
玩家一:拿9

此时样例:2
玩家二:拿2,结束。

那么如何计算他们的分数呢,这就需要我们定义一个二维DP,可以看出样例中区间长度时不断递减的,每一次决策都会减少一个数,那么一个状态的DP可以由前一个状态转移过来,前一个要么取左边要么取右边,形成了此状态的DP,这不就是区间DP吗,dp[i][j]表示区间下表为i~j先手人获得的最大分数

状态转移方程:dp[i][j]=max(w[i]+\sum w[k] (i<k<=j)-dp[i+1][j],  w[i]+ \sum w[k](i<=k<j)-dp[i][j-1])

这里定义的是dp[i][j]表示区间下表为i~j先手人获得的最大分数,假设选左边最优,既然选了那就要+w[i],为什么还要加上一个区间和(i<k<=j)还要减去dp[i+1][j],这里解释一下,既然选了左端点,那么区间就变为[i+1,j],玩家二的最优决策肯定时是dp[i+1][j],这个状态去转移玩家二下一次的最优决策,presum[j]-presum[i]为玩家二所能选的区间和,减去玩家二的最优决策所获得的分数,那么剩下的就是玩家一前一个状态的累计分数。

为了我们的状态能由上一个小状态转移过来,我们外循环枚举区间长度,这样保证了状态转移方程里面的数据已经更新了,内循环枚举区间起点,知道起点和区间长度,那么终点就可以计算出来。


AC代码:

#include<iostream>
using namespace std;
int n;
int w[105],dp[105][105],presum[105];//dp[i][j]为区间为i~j先手获得最大分数
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>w[i];presum[i]=presum[i-1]+w[i];}//区间DPfor(int len=1;len<=n;len++){//枚举区间长度for(int i=1;i+len-1<=n;i++){//枚举左端点int j=i+len-1;//右端点dp[i][j]=max(w[i]+presum[j]-presum[i]-dp[i+1][j],w[j]+presum[j-1]-presum[i-1]-dp[i][j-1]);//状态转移}}cout<<dp[1][n]<<" "<<presum[n]-dp[1][n]<<endl;return 0;
}

题后总结:

这道题跟蓝桥杯练习系统的一个题很像,但好久没有写了,也忘记思路的,区间DP感觉很难理解,代码倒是很简洁。y总讲的是另一种定义,dp的含义是先手玩家与后手玩家分数的差值,虽然好理解一点,但是这种定义一般是想不出来的,这里就用了最一般的定义去写的,望大家理解。重难点在于状态转移方程,建议自己模拟一下过程,就很好理解了,文章说的比较多,若有错误的地方请大家指出,感谢观看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/599687.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ctfshow web入门 命令执行 web53--web77

web53 日常查看文件 怎么回事不让我看十八 弄了半天发现并不是很对劲&#xff0c;原来我发现他会先回显我输入的命令再进行命令的回显 ?cnl${IFS}flag.php||web54 绕过了很多东西 基本上没有什么命令可以用了但是 grep和?通配符还可以用 ?cgrep${IFS}ctfshow${IFS}???…

hadoop分布式计算组件

什么是计算、分布式计算&#xff1f; 计算&#xff1a;对数据进行处理&#xff0c;使用统计分析等手段得到需要的结果 分布式计算&#xff1a;多台服务器协同工作&#xff0c;共同完成一个计算任务 分布式计算常见的2种工作模式 分散->汇总(MapReduce就是这种模式)中心调…

一起学习python——基础篇(8)

今天讲一下python的关键字。 关键字是什么&#xff1f;关键字是有特别意义的标识符&#xff08;编程语言事先定义好的&#xff09;&#xff0c;也叫保留字。关键字不能用作变量名&#xff0c;函数名&#xff0c;参数。 关键字有哪些&#xff1f;我大概列一下&#xff1a;if、…

KingbsaeES数据库分区表的详细用法

数据库版本&#xff1a;KingbaseES V008R006C008B0014 简介 分区表是一种将大型数据库表拆分为更小、更可管理的部分的技术。它通过将表数据分散存储到多个物理存储单元中&#xff0c;可以提高查询和数据维护的性能&#xff0c;并优化对大型数据集的处理。本篇文章以kingbase为…

4月7号总结

java学习 一.正则表达式 定义&#xff1a;正则表达式是一种用于描述字符串模式的表达式&#xff0c;通常被用于文本搜索、匹配和替换。它是一种强大的工具&#xff0c;可以在文本处理和文本分析中进行复杂的匹配和操作。 通过字符串引用里面的方法matches&#xff0c;然后执行…

多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络多输入多输出预测

多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络…

有原则的程序员如何超越竞争对手(附演讲视频》

接受干净的编码实践&#xff0c;建立可维护的代码结构&#xff0c;并有效地管理自己&#xff0c;对于成为当今专业行业中具有竞争力和受欢迎的程序员至关重要。 在本指南中&#xff0c;我们将探讨每个熟练的程序员都应该精通的基本编码主题&#xff1a; - 遵守编程标准 …

2024年MathorCup妈妈杯数学建模思路C题思路解析+参考成品

1 赛题思路 (赛题出来以后第一时间在群内分享&#xff0c;点击下方群名片即可加群) 2 比赛日期和时间 报名截止时间&#xff1a;2024年4月11日&#xff08;周四&#xff09;12:00 比赛开始时间&#xff1a;2024年4月12日&#xff08;周五&#xff09;8:00 比赛结束时间&…

51单片机之串口通信

目录 1.串口简介 1.1TXD和RXD 1.2通讯接口 1.3通信方式 1.4 51单片机的UART模式 2.串口配置 2.1寄存器简介 SCON寄存器配置 PCON配置 2.2代码配置串口 2.2.1 配置串口发送数据 2.2.2配置电脑向单片机发送数据点亮LED 1.串口简介 串口是一个应用十分广泛的通讯接口&am…

数据恢复与数据取证的便携工具:PC-3000 Portable III

天津鸿萌科贸发展有限公司从事数据安全业务20余年&#xff0c;在数据恢复、数据取证、数据备份等领域有丰富的案例经验、前沿专业技术及良好的行业口碑。同时&#xff0c;公司面向取证机构及数据恢复同行&#xff0c;提供实验室建设方案&#xff0c;包含数据恢复与数据取证硬件…

怎么把学浪的视频保存到手机

越来越多的人在学浪app里面购买了课程并且想要下载下来&#xff0c;但是苦于没有方法或者工具&#xff0c;所以本文将教大家如何把学浪的视频保存到手机随时随地的观看&#xff0c;再也不用担心课程过期的问题。 本文将介绍工具来下载&#xff0c;因为下载方法太复杂&#xff…

4.6java学习总结

内部类(补充) 局部内部类 如果在外界定义会检测不到你所定义的局部内部类,直接报错. public class Main {public static void print(int age,int b){class person{int age;public person(int age) {this.age age;}void show(){System.out.println("内部类输出: "a…