2021春季学期华清大学EE数算OJ3:岩石的重量
原题目如下:
看起来,这不过是我们在《程序设计基础》里面接触过的简单动态规划问题(
什么,你不知道什么叫动态规划?
什么是动态规划?
百度百科对“动态规划”一词定义如下:在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。因此各个阶段决策的选取不能任意确定,它依赖于当前面临的状态,又影响以后的发展。当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线.这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问题称为多阶段决策问题。在多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化的过程为动态规划方法 。
但这样的定义谁也读不下去不是吗,因此,思考这样一个问题:
《程序设计基础》中,老师曾经讲过,对于“求斐波那契数列”这道题,用递推的办法比递归的办法更快。我们分别分析一下这两种办法。
假设我们需要求解f(6),对于递推法,我们只需要求解f5+f4,且这两者已经被我们求出来了。而对于递归法,f5和f4需要我们再调用函数求解,他们分别的求解过程中还需要继续套娃。。。
比较两种方法,我们不难发现,递推法把问题分成了若干小问题,而对于部分问题的解进行了存储,这样就使得如果我们希望多次调用一个中间值,无需反复递归求解。这就是一种dp(动态规划)的思想。
以这道题为例,我们就可以存储下每次取完石头后,对于不同位置的重量最大值,这样在进行下一步时,无需进行反复的递归。
用朴素的dp思想试做这道题
原题中对dp思想给予的温馨提示:
(其实这个提示已经将dp的具体实现告诉大家了)
读者可以自己尝试根据上述提示写出一个dp程序。
之所以这样dp,是因为如果确定了i轮选择和左边取出j个石头,无论前i-1的选择情况是怎样的,都不会对后续选择造成任何影响。
如果自己不能写出这个dp程序,下面是几点提示:
1.找到动态规划状态转移方程。dp就是由初始状态,边界条件,停止条件和状态转移方程组成的。对于这道题来说,在每个地方的状态转移方程都是等价的,没有什么特殊的干扰条件。
2.上述的i,j其实提示了实现循环的方法,可以发现按照这两个循环变量进行循环,恰好没有丢失或多步骤,而且步骤的顺序是满足本身的因果关系的。
3.最终得到的是一个一维数组,存储了左指针(j)在各个位置的选取最优解。只需在这些最优解中再取最优解即可。
如果你写出了这个dp程序,你会发现并不能够ac此题,而且,出现了一种罕见的错误类型,叫做:
如何降低空间复杂度?
本题的内存限制为20000kb,显然,并不能支撑我们开启1000*1000的二维数组。这就考验我们能否将空间复杂度进一步降低呢?
其实本题用到的优化也是在dp中非常常见的:我们发现,在状态转移方程中,第i轮的数值永远只和第i-1轮相关,而且我们在更新的时候,也是按照i的增加顺序更新的,也就是说,在更新第i次选取时,第i-2及以前的数据,我们是已经用不到的。这也就是说,我们可以用两个一维数组循环求解来代替原来的二维数组。
为了书写方便,我采用了一个第二维大小为2的二维数组。代码如下
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<string>
using namespace std;
int d[2][30005],g[30005];
inline void read(int&x){
char c,f=x=0;
while(!isdigit(c=getchar()))f=c=='-';
while(isdigit(c))x=x*10-48+c,c=getchar();
if(f)x=-x;
}
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)read(g[i]);
int p=0;
for(int k=1;k<=n/2;k++){
int q=p^1;
for(int r=0;r<=2*k;r++){ //左指针为r,即第r个石头在第k次后被取走了
if(!r)d[q][r]=d[p][r]+g[r+n+2-2*k];
else if(r==1)d[q][r]=max(d[p][r]+g[r+n+2-2*k],d[p][r-1]+max(g[r],g[r+n-2*k+1]));
else if(r==2*k-1)d[q][r]=max(d[p][r-1]+max(g[r],g[r+n-2*k+1]),d[p][r-2]+g[r-1]);
else if(r==2*k)d[q][r]=d[p][r-2]+g[r-1];
else d[q][r]=max(d[p][r-1]+max(g[r],g[r+n-2*k+1]),max(d[p][r-2]+g[r-1],d[p][r]+g[r+n+2-2*k]));
}
p=p^1;
}
int ma=0,k=n/2;
for(int i=2;i<=n+1;i++){ma=ma>d[k&1][i]?ma:d[k&1][i];}
printf("%d",ma);
}
(依然采用了快读,喜提472ms)
(求广大dalao教教如何进一步优化)
2021春季学期华清大学EE数算OJ3:岩石的重量的更多相关文章
- 2021夏季学期华清大学EE数算OJ2:难缠的店长
2021年夏季学期华清大学电子系数算oj2题解 某知名oier锐评蒟蒻的oj1题解: 话不多说,进入oj2题解: 难缠的oj 之 难缠的店长 当时读完我已经因为无良甲方的行为出离愤怒了!但是做题还是要 ...
- 2021夏季学期华清大学EE数算OJ1:算数问题
第一次写博客,有点紧张... 也许格式也没有特别丑吧 先看原题( 此题做法众多,这里仅仅介绍蒟蒻的一种很复杂的思路(但最后还是喜提0ms的好成绩) 读完这道题,不难发现,此题不过是一个质因数分解+一堆 ...
- 2019年春季学期第四周作业Compile Summarize
这个作业属于哪个课程 C语言程序设计一 这个作业要求在哪里 2019春季学期第四周作业 我的课程目标 重新学习有关数组的问题 这个作业在哪个具体方面帮助我实现目标 对于置换有了新的见解 参考文献 中国 ...
- 毕业样本=[华威大学毕业证书]Warwick原件一模一样证书
华威大学毕业证[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...
- 热烈庆祝华清远见2014嵌入式系统(Linux&Android)开发就业培训课程全面升级
近日,华清远见公开宣布:2014嵌入式系统 (Linux&Android)开发就业培训课程再次升级!据悉,华清远见如今已经持续10年,一直保持课程每年2次的更新的频率.华清远见的每 次课程更新 ...
- 百度前端技术学院(IFE)2016春季学期总结
今天(5月16日)作为第八个提交者提交了任务五十:RIA微型问卷管理平台 这样一个综合性的大任务,宣告我的IFE春季学期课程学习顺利完成.其实任务五十并不复杂,现在再让我来做,可能一周不到就写出来了, ...
- 2019年春季学期《C语言程序设计II》助教注意事项
本学期<C语言程序设计II>课程安排 理论课时24(1-12周),实验课时8(13周),课程设计课时16(14-15周) 理论课教学内容 附:教学进度表 本学期实验课和课程设计参考教材 & ...
- 2019年春季学期《C语言程序设计II》课程总结
2019年春季学期<C语言程序设计II>课程总结 1.课程情况 教学内容 课堂小结 作业安排 优秀作业 备注 1.开学谈心 2.测验数据类型.运算符与表达式的自学情况,并讲解测验题目3.第 ...
- 基于华清远见STM32f051的 IIC从模式实现方法
作者:卢老师,华清远见嵌入式学院讲师. 在大多情况下,我们使用MCU控制传感器,节点以及相关从设备,但在较为复杂的系统中,有时候也会使用MCU做为从设备. 下面是关于stm32f051的从模式实现方法 ...
随机推荐
- BMZCTF ssrfme
<?php if(isset($_GET) && !empty($_GET)){ $url = $_GET['file']; $path = "upload/" ...
- 03. Pandas数据结构
03. Pandas数据结构 Series DataFrame 从DataFrame中查询出Series 1. Series Series是一种类似于一维数组的对象,它由一组数据(不同数据类型)以及一 ...
- DOM 小总结
DOM 是什么 文档对象模型,是针对 HTML 和 XML 文档的一个 API (应用程序编程接口), 描绘了一个层次化的节点树. D: document 当 web 浏览器浏览一个页面的时候,DOM ...
- CSS 常用的定位和布局方法汇总(已添加源码地址)
CSS-Layout 旨在打造详尽的前端布局代码学习库(自从用了框架开发,CSS生疏了不少,所以开这个库练练手)SF不能正确解析含有中文的网址,所以某些预览链接无法跳转,请访问我的博客阅读此文 常见定 ...
- Mpvue 小程序转 Web 实践总结
介绍 Mpvue 是一个使用 Vue.js 开发小程序的前端框架.框架基于 Vue.js 核心,修改了 Vue.js 的 runtime 和 compiler 实现,使其可以运行在小程序环境中,从而为 ...
- ES6-11学习笔记--数组的扩展
类数组 / 伪数组 Array.from() Array.of() copyWithin() fill() includes() 类数组.伪数组例子: let divs = document.ge ...
- hive从入门到放弃(四)——分区与分桶
今天讲讲分区表和分桶表,前面的文章还没看的可以点击链接: hive从入门到放弃(一)--初识hive hive从入门到放弃(二)--DDL数据定义 hive从入门到放弃(三)--DML数据操作 分区 ...
- tkinter GUI编程
tkinter编程概述 tkinter模块包含在Python的基本安装包中.使用tkinter模块编写的GUI程序是跨平台的.可在windows.UNIX.Linux以及Macintonsh OS X ...
- golang开发:go并发的建议
这个是前段时间看到Go语言的贡献者与布道师 Dave Cheney对Go并发的建议或者叫使用的陷阱(不是我自己的建议),结合自己最近几年对gorotine的使用,再回头看这几条建议,真的会茅塞顿开,觉 ...
- jdk-1.8环境变量配置
1.首先下载好jdk-1.8的安装包. 这个安装也是傻瓜式安装,一直下一步即可.一定要记得中间你所设置的安装路径 2.切记 切记 jdk的安装路径 ! 3.右键"此电脑",点击最下 ...