2020安徽省大学生程序设计大赛题解——F 跳蛙出行

F 跳蛙出行

池塘里有n片荷叶排成一行,有一只青蛙在上面跳跃。但是,这只青蛙是只不同寻常的青蛙,它每跳一次,只能从一片荷叶跳到相邻的荷叶上,并且,它在两片荷叶之间,只能跳跃有限次。青蛙可以从任意荷叶出发。问它最多能跳多少次。

题目

标签

数组、二维动态规划

分析


图 F − 1 对 于 样 例 数 据 的 展 示 图F-1 \ \ \ \ 对于样例数据的展示 图F−1    对于样例数据的展示

设青蛙运动的起点为 A A A、终点为 B B B。

对于青蛙任意的运动过程,我们都可以将其等价为三段运动:

  • 过程一 从 A A A点向左(右)运动并返回 A A A点。
  • 过程二 从 A A A点运动到 B B B点。
  • 过程三 从 B B B点向右(左)运动并返回 B B B点。

我们可以结合样例来理解上述描述。


图 F − 2 对 三 段 过 程 的 展 示 图F-2 \ \ \ \ 对三段过程的展示 图F−2    对三段过程的展示

有了这三段运动,现在只需求得三段运动的跳跃次数之和的最大值。我们将其分成两个子问题:

子问题一:对于选定的起点和终点,求解过程一和过程三的最大跳跃次数之和

我们希望青蛙能尽可能的跳更多次,即对于选定的起点和终点(也就是过程二被确定),我们希望过程一和过程三的步数尽可能多。

令起点坐标为 i i i,终点坐标为 j j j, l [ i ] l[i] l[i]表示 i i i点向左边跳,且最后回到 i i i点最多能走多少步;令 r [ j ] r[j] r[j]表示 j j j点向右边跳,且最后回到 j j j点最多能走多少步。

用 a [ i ] a[i] a[i]表示两点之间能跳跃的最多次数,则 l l l、 r r r可以用递推的方法算出。值得注意的是,如果两个点之间能够跳跃的次数是奇数次,在计算 l [ i ] l[i] l[i]时我们只能取 a [ i ] − 1 a[i]-1 a[i]−1,原因是想要完成往返运动,路径上每相邻两荷叶的间隔都只能被经过偶数次。

for (int i = 1; i < n - 1; i++) {if (a[i] > 1) {l[i] = l[i - 1] + a[i] % 2 ? a[i] - 1 : a[i];}
}
for (int i = n - 2; i >= 0; i--) {if (a[i + 1] > 1) {r[i] = r[i + 1] + a[i + 1] % 2 ? a[i + 1] - 1 : [i + 1];}
}

这样,我们就找到了过程一、三这两个子问题的最优解。

过程二是由区间确定的值,我们用 d i s [ i ] dis[i] dis[i]表示从 1 1 1个荷叶开始,走到 i i i个荷叶,最多能跳多少次。则从第 i i i个荷叶跳到第 j j j个荷叶最多跳跃次数为 ∣ d i s [ j ] − d i s [ i ] ∣ \vert dis[j]-dis[i]\vert ∣dis[j]−dis[i]∣。

我们可以这样求得 d i s [ i ] dis[i] dis[i]。

dis[1] = a[1] % 2 ? a[1] : a[1] - 1;
for (int i = 2; i < n; i++) {dis[i] = (dis[i - 1] + a[i] % 2 ? a[i] : a[i] - 1);
}

基于上述描述,利用 l [ i ] l[i] l[i]、 r [ i ] r[i] r[i]、 d i s [ i ] dis[i] dis[i],对于任意一组起点和终点,我们都可以求出本题的一组最优解了,过程一的最优解为 l [ i ] l[i] l[i],过程二的最优解为 r [ j ] r[j] r[j],过程三的最优解为 − d i s [ i ] + d i s [ j ] ( j > i ) -dis[i]+dis[j](j > i) −dis[i]+dis[j](j>i),那么整个问题的答案可用一个表达式描述。

ans = l[i] - dis[i] + r[j] + dis[j]
子问题二:选定最优解的起点和终点

现在问题在于,该如何找到最优解的起点和终点。想确定最优解对应的起点和终点,最朴素的想法是二重循环,但该方法会超时。为了优化算法,我们从三段过程对最优解的贡献出发,考虑二维动态规划可以在子问题之间无相互干扰时,利用动态规划的无后效性进行时间复杂度的简化。

这道题可以求出终点 j j j在任意位置时,找到 i i i对应的最优解,最后把两个子问题合并来得出最终答案。对于满足 { i ∣ 0 < i < = j } \{i \ \vert \ 0 < i< =j \} {i ∣ 0<i<=j}的所有 i i i,我们都可以寻找出 l [ i ] − d i s [ i ] l[i] - dis[i] l[i]−dis[i]的最优解,并将其记录在 m a x l maxl maxl中,以此用一重循环解决二位动态规划问题。

我们用 a n s ans ans记录最终答案,那么每一次终点后移, m a x l maxl maxl都会斟酌 i i i在新的位置(即i=j)时是否会使得 m a x l maxl maxl获得更优解,如图所示。


图 F − 3 m a x l 的 初 态 图F-3 \ \ \ \ maxl的初态 图F−3    maxl的初态


图 F − 4 m a x l 的 末 态 图F-4 \ \ \ \ maxl的末态 图F−4    maxl的末态

求得 m a x l maxl maxl后,利用相同的方法,我们即可求解出整个问题的最优解。

long long ans = l[0] + r[0];
long long maxl = l[0];
for (int j = 1; j < n; j++) {int i = j;maxl = max(maxl, l[i] - dis[i]);ans = max(ans, r[j] + dis[j] + maxl);
}

参考答案(C++)

#include <bits/stdc++.h>
using namespace std;long long l[200005], r[200005], dis[200005];
//l[i]表示i点向左边走,且最后回到i点最多能得多少分
//r[i]表示i点向右走,且最后回到i点最多能得多少
//dis[i]表示,从1号桥开始,走到i号桥,最多能得多少分
//求l[i] - dis[i] + r[j] + dis[j]int n;
long long a[200005];long long cal(long long x) {return x % 2 ? x - 1 : x;
}
set <long long> s;int main()
{std::ios::sync_with_stdio(false);cin >> n;for (int i = 1; i < n; i++) {cin >> a[i];}for (int i = 1; i < n - 1; i++) {if (a[i] > 1) {l[i] = l[i - 1] + cal(a[i]);}}for (int i = n - 2; i >= 0; i--) {if (a[i + 1] > 1) {r[i] = r[i + 1] + cal(a[i + 1]);}}dis[1] = cal(a[1] - 1) + 1;for (int i = 2; i < n; i++) {dis[i] = (dis[i - 1] + cal(a[i] - 1) + 1);}long long ans = l[0] + r[0];long long maxl = l[0];for (int i = 1; i < n; i++) {maxl = max(maxl, l[i] - dis[i]);ans = max(ans, r[i] + dis[i] + maxl);}cout << ans;return 0;
}

2020安徽省大学生程序设计大赛题解——F 跳蛙出行相关推荐

  1. 2020安徽省大学生程序设计大赛题解——J 飞奔的战士

    2020安徽省大学生程序设计大赛题解--J 飞奔的战士 J 飞奔的战士 题目 众所周知, T e u t o n i c K n i g h t Teutonic Knight TeutonicKni ...

  2. 2020安徽省大学生程序设计大赛题解——E 收集圣物

    2020安徽省大学生程序设计大赛题解--E 收集圣物 E 收集圣物 在一个策略游戏中,僧侣单位可以收集圣物,放入修道院中,以生产黄金.因此,圣物对赢得游戏的胜利很重要. 某个僧侣正处于一个长为n 宽为 ...

  3. 2020安徽省大学生程序设计大赛题解——A数字排列

    2020安徽省大学生程序设计大赛题解--A数字排列 A 数字排列 给出两个整数A 和 B,可以重新排列A 得到新的数字C(不能有前导0).求在小于等于B的情况下,C的最大值是多少.如果不存在输出-1. ...

  4. 2020安徽省大学生程序设计大赛题解——K 农夫打狼

    2020安徽省大学生程序设计大赛题解--K 农夫打狼 K 农夫打狼 题解 标签 排序,动态规划 分析 图K−1本题的一个样例,彩色十字为起点和终点图K-1 \ \ \ \ 本题的一个样例,彩色十字为起 ...

  5. “Shopee杯” e起来编程暨武汉大学2020年大学生程序设计大赛决赛(重现赛)

    比赛链接 文章目录 A题 A Simple Problem about election 题目描述 题解: 代码: D题 Deploy the medical team 题意: 题解: 代码: F题 ...

  6. 2017年“华信智原杯”安徽省大学生程序设计大赛C题-刷票

    C. 刷票 题目描述: 有一个选秀比赛,节目组按照观众的投票情况决定选手的去留.为了给旗下 艺人造势,A 公司收买了一批水军来刷票.已知现在有 n 名选手同台竞争,依次 编号 1-n,A 公司的艺人编 ...

  7. 2022年安徽省机器人大赛——程序设计赛道 第十三届安徽省大学生程序设计大赛————I 玩捉迷藏

    (建议直接观看后面图片,图片更生动哦) 首先看这个题目,这个题目也是比较简单得,最主要就是读懂这个题目,因为我感觉这个题目还是比较绕人的. 首先我们来分析一下题目,"小明可以使用 Cij个航 ...

  8. 2020 乐山师范学院新生程序设计大赛题解

    2020 乐山师范学院新生程序设计大赛题解 A 数组求和 中等难度 题目大意: 给定一个数组,执行若干次操作,每次操作可以把两个相邻的数变成相反数,求数组最大的和. 解题思路: 这其实是一个思维题,认 ...

  9. 金莹江苏省计算机学会教授,2020年江苏省大学生程序设计大赛在我校举办

    11月15日,2020年江苏省程序设计大赛在河海大学举办.河海大学副校长董增川教授.江苏省计算机学会秘书长金莹教授出席闭幕式并致辞. 河海大学副校长董增川教授在致辞中表示,河海大学不断深化教育教学改革 ...

最新文章

  1. 14_传智播客iOS视频教程_instancetype
  2. 60、IPv6配置实验之RIP
  3. 【工具】统计jar包和apk中的java方法数
  4. BZOJ-1864-[Zjoi2006]三色二叉树(树形dp)
  5. red hat linux 7.1 使用手册!,Red Hat Linux 7.1使用手册(中)
  6. Symantec防病毒企业版10.1部署方法一
  7. 关于 jsp java servlet 中文汉字乱码的解决方法
  8. 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛(同步赛)解题报告
  9. C++中对字符串的分割方法
  10. Python安装时import matplotlib.pyplot as plt报错
  11. linux redis 启动_Redis系列:单机主从模式搭建
  12. 2021年中国机动车保有量及机动车污染物排放情况分析[图]
  13. 无损连接,函数依赖性判定
  14. 判断当前是在ie还是谷歌
  15. 国庆黄金周...HAPPY
  16. 对炒股的一点个人浅见
  17. Windows 10如何进入和退出安全模式
  18. 三星note10 android11,安卓 11 来了,三星 Galaxy Note 10 系列升级 One UI 3.0
  19. 交换机的连接方式详解(图)
  20. 用linux系统做数字钟,大强学易之易语言实例:简单的易语言桌面电子时钟

热门文章

  1. 华为OD机试 - 找数字、找等值元素(Java JS Python)
  2. 2020年蓝桥杯省赛题目——既约分数
  3. 基础集合论 第一章 集合与集合的运算
  4. ACM MM 2020大奖项出炉!南开获最佳论文奖,西安交大获最佳学生论文奖
  5. VMware 随win10自动启动与关闭
  6. 来自阿里前端的一些中肯建议
  7. 被删短信通讯运营商仍保存半年
  8. 计算方法实验(三):四阶龙格-库塔方法
  9. 游戏建模基本流程(讲解建模经验)
  10. Autodesk(欧特克)公司的主要产品介绍