原题目如下:

看起来,这不过是我们在《程序设计基础》里面接触过的简单动态规划问题(
什么,你不知道什么叫动态规划?

什么是动态规划?

百度百科对“动态规划”一词定义如下:在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。因此各个阶段决策的选取不能任意确定,它依赖于当前面临的状态,又影响以后的发展。当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线.这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问题称为多阶段决策问题。在多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化的过程为动态规划方法 。
但这样的定义谁也读不下去不是吗,因此,思考这样一个问题:
《程序设计基础》中,老师曾经讲过,对于“求斐波那契数列”这道题,用递推的办法比递归的办法更快。我们分别分析一下这两种办法。
假设我们需要求解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:岩石的重量的更多相关文章

  1. 2021夏季学期华清大学EE数算OJ2:难缠的店长

    2021年夏季学期华清大学电子系数算oj2题解 某知名oier锐评蒟蒻的oj1题解: 话不多说,进入oj2题解: 难缠的oj 之 难缠的店长 当时读完我已经因为无良甲方的行为出离愤怒了!但是做题还是要 ...

  2. 2021夏季学期华清大学EE数算OJ1:算数问题

    第一次写博客,有点紧张... 也许格式也没有特别丑吧 先看原题( 此题做法众多,这里仅仅介绍蒟蒻的一种很复杂的思路(但最后还是喜提0ms的好成绩) 读完这道题,不难发现,此题不过是一个质因数分解+一堆 ...

  3. 2019年春季学期第四周作业Compile Summarize

    这个作业属于哪个课程 C语言程序设计一 这个作业要求在哪里 2019春季学期第四周作业 我的课程目标 重新学习有关数组的问题 这个作业在哪个具体方面帮助我实现目标 对于置换有了新的见解 参考文献 中国 ...

  4. 毕业样本=[华威大学毕业证书]Warwick原件一模一样证书

    华威大学毕业证[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...

  5. 热烈庆祝华清远见2014嵌入式系统(Linux&Android)开发就业培训课程全面升级

    近日,华清远见公开宣布:2014嵌入式系统 (Linux&Android)开发就业培训课程再次升级!据悉,华清远见如今已经持续10年,一直保持课程每年2次的更新的频率.华清远见的每 次课程更新 ...

  6. 百度前端技术学院(IFE)2016春季学期总结

    今天(5月16日)作为第八个提交者提交了任务五十:RIA微型问卷管理平台 这样一个综合性的大任务,宣告我的IFE春季学期课程学习顺利完成.其实任务五十并不复杂,现在再让我来做,可能一周不到就写出来了, ...

  7. 2019年春季学期《C语言程序设计II》助教注意事项

    本学期<C语言程序设计II>课程安排 理论课时24(1-12周),实验课时8(13周),课程设计课时16(14-15周) 理论课教学内容 附:教学进度表 本学期实验课和课程设计参考教材 & ...

  8. 2019年春季学期《C语言程序设计II》课程总结

    2019年春季学期<C语言程序设计II>课程总结 1.课程情况 教学内容 课堂小结 作业安排 优秀作业 备注 1.开学谈心 2.测验数据类型.运算符与表达式的自学情况,并讲解测验题目3.第 ...

  9. 基于华清远见STM32f051的 IIC从模式实现方法

    作者:卢老师,华清远见嵌入式学院讲师. 在大多情况下,我们使用MCU控制传感器,节点以及相关从设备,但在较为复杂的系统中,有时候也会使用MCU做为从设备. 下面是关于stm32f051的从模式实现方法 ...

随机推荐

  1. 学习GlusterFS(九)

    环境说明: 3台机器安装 GlusterFS 组成一个集群. 使用 docker volume plugin GlusterFS 服务器: 10.6.0.140 10.6.0.192 10.6.0.1 ...

  2. 决策树3:基尼指数--Gini index(CART)

    既能做分类,又能做回归.分类:基尼值作为节点分类依据.回归:最小方差作为节点的依据. 节点越不纯,基尼值越大,熵值越大 pi表示在信息熵部分中有介绍,如下图中介绍 方差越小越好. 选择最小的那个0.3 ...

  3. 【动态系统的建模与分析】8_频率响应_详细数学推导 G(jw)_滤波器

  4. SQL之总结(一)

    导游通项目之总结SQL 1.选择前面的某几个 oracle:  select * from tb_article where rownum<5 order by article_id       ...

  5. Codepen 每日精选(2018-3-24)

    按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以打开原始页面. 纯 css 画的抽象小鸟https://codepen.io/gregoryb/f... 纯 css 制作 ...

  6. PAT B1081 检查密码

    题目描述: 本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能.该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母.数字和小数点 .,还必须既有字母也有数字. 输入格式: ...

  7. 将本地项目上传到gitLab操作

    在设置好SSH之后,执行下面的操作即可完成: git init    //  初始化git status  //查看提交文件状态git remote add origin git地址   //  连接 ...

  8. 帝国CMS批量提取正文内容到简介

    最近接到一个帝国CMS模板改版项目,自带的数据可能是采集的,以前的简介字段内容只截取了60个字,新模板的简介60字符太少了,不美观,想让简介都截取200个字,怎么批量修改呢,文章太多了手动改肯定不行, ...

  9. css 实现球里装水

    <template> <div class="container">     <div class="wave"></ ...

  10. 前端性能优化之js,css调用优化

    规则1:减少HTTP请求     把多个JS请求合并为一个JS请求,把多个CSS请求合并为一个CSS请求.从而减少从客户端向服务器端的请求数.     规则3:添加Expires头     用http ...