学习内容

动态规划:解决多阶段决策问题的一种方法。实际上就是一种排除重复计算的算法,更具体的说,动态规划就是用空间换取时间。

多阶段决策问题:若一类问题的求解过程可分为若干个互相联系的阶段,在每一个阶段都需作出决策,并影响到下一个阶段的决策。这类问题的解决,就是要在可以选择的那些策略间,选一个最优策略,使在预定的标准下达到最好的效果。

阶段:将所给求解问题的过程恰当地分成若干个相互联系的阶段,以便于求解,过程不同,阶段数就可能不同,描述阶段的变量称“阶段变量”。

状态:描述事物的性质,不同事物有不同的性质,因而用不同的状态来刻画。对问题的求解状态的描述是分阶段的。描述状态的量称“状态变量”

状态转移方程:用数学公式描述与阶段相关的状态间的演变规律。是本阶段的状态往往是上一阶段状态和上一阶段决策的结果。如果给定了第K阶段的状态Sk以及决策uk(Sk),则第K+1阶段的状态Sk+1也就完全确定。

动态规划将问题分为多个阶段,并对多个阶段分别进行分析和解决,最后求得整体解。需要注意的是,动态规划问题的每个阶段都会对下一阶段产生影响,并且这影响是需要计算在下一阶段中的,

现在所接触的动态规划问题为线性DP,经过查询资料后了解到动态规划还有:区间DP,状压DP,数位DP,树形DP等分类,随着学习的深入,相信对其他方面也会有所涉猎。

问题解决

最大2子段和

Input

The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input.
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.

Output

Print exactly one line for each test case. The line should contain the integer d(A).

很显然这题为一个求最大二子段和问题,面对动态规划,首先还是有些麻爪的,不过好在求解动态规划有求解的一般步骤,跟随着步骤一步步进行分析,最终就会得到答案;

用t[i]来存储以a[i]结尾的最大子段和,则t[i]=max(t[i-1]+a[i],a[i]),把本问题可分为左字段和右字段两部分,2子段和就为左字段加上右字段。

想法很美好,但是在提交的时候出现了较多的问题,在多次确认编译运行结果之后发现并无错误,但是在提交后总是显示time limit错误,我以为是网络问题导致提交延迟,查询资料也没找到结果,询问了几个同学都表示出现这种情况,没办法,只能一步步试探了。

首先是常规写法,我保留了自己的写法习惯对代码进行了调整,但是错误依旧。

//time limit
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<iomanip>
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;
int main()
{int t,n,a[50000+10],i,maxx=0;int tem[50000+10],ans[50000+10];cin>>t;while(t--){maxx=0;cin>>n;for(i=1;i<=n;i++)cin>>a[i];memset(tem,0,sizeof(tem));memset(ans,0,sizeof(ans));tem[1]=a[1];ans[n]=a[n];for(i=2;i<=n;i++){tem[i]=max(tem[i-1]+a[i],a[i]);}for(i=2;i<=n;i++){tem[i]=max(tem[i],tem[i-1]);}for(i=n-1;i>=1;i--){ans[i]=max(ans[i+1]+a[i],a[i]);maxx=max(maxx,tem[i]+ans[i+1]);}cout<<maxx<<endl;}return 0;
}

然后,我参照同学的意见把cin更改为了scanf,结果出人意料,居然不再报错time limit了,但是差强人意,结果为wrong anwser

//wrong answer
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<iomanip>
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;
int main()
{int t,n,a[50000+10],i,maxx=0;int tem[50000+10],ans[50000+10];cin>>t;while(t--){maxx=0;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&a[i]);memset(tem,0,sizeof(tem));memset(ans,0,sizeof(ans));tem[1]=a[1];ans[n]=a[n];for(i=2;i<=n;i++){tem[i]=max(tem[i-1]+a[i],a[i]);}for(i=2;i<=n;i++){tem[i]=max(tem[i],tem[i-1]);}for(i=n-1;i>=1;i--){ans[i]=max(ans[i+1]+a[i],a[i]);maxx=max(maxx,tem[i]+ans[i+1]);}printf("%d\n",maxx);}return 0;
}

又经过多次试探,用最笨的排除法发现,使用max函数时求解最大值, 存储最大值的变量初值不能为零,将变量初始化为负无穷后居然AC了,震惊。。。。

关于无穷量的设定我曾问过学长,说是常用0x3f3f3f3f,百度查询了一下得到以下结论:

0x3f3f3f3f的十进制是1061109567,是10^9级别的(和0x7fffffff一个数量级),而一般场合下的数据都是小于10^9的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形。
另一方面,由于一般的数据都不会大于10^9,所以当我们把无穷大加上一个数据时,它并不会溢出(这就满足了“无穷大加一个有穷的数依然是无穷大”),事实上0x3f3f3f3f+0x3f3f3f3f=2122219134,这非常大但却没有超过32-bit int的表示范围,所以0x3f3f3f3f还满足了我们“无穷大加无穷大还是无穷大”的需求。

//转载于:https://blog.csdn.net/jiange_zh/article/details/50198097

//AC
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<iomanip>
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;
int main()
{int t,n,a[50000+10],i,maxx=0;int tem[50000+10],ans[50000+10];cin>>t;while(t--){maxx=-INF;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&a[i]);memset(tem,0,sizeof(tem));memset(ans,0,sizeof(ans));tem[1]=a[1];ans[n]=a[n];for(i=2;i<=n;i++){tem[i]=max(tem[i-1]+a[i],a[i]);}for(i=2;i<=n;i++){tem[i]=max(tem[i],tem[i-1]);}for(i=n-1;i>=1;i--){ans[i]=max(ans[i+1]+a[i],a[i]);maxx=max(maxx,tem[i]+ans[i+1]);}printf("%d\n",maxx);}return 0;
}

不得不感叹这东西是真的奇妙。。。

Milking Time

Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to schedule her next N (1 ≤ N ≤ 1,000,000) hours (conveniently labeled 0..N-1) so that she produces as much milk as possible.

Farmer John has a list of M (1 ≤ M ≤ 1,000) possibly overlapping intervals in which he is available for milking. Each interval i has a starting hour (0 ≤ starting_houri ≤ N), an ending hour (starting_houri < ending_houri ≤ N), and a corresponding efficiency (1 ≤ efficiencyi ≤ 1,000,000) which indicates how many gallons of milk that he can get out of Bessie in that interval. Farmer John starts and stops milking at the beginning of the starting hour and ending hour, respectively. When being milked, Bessie must be milked through an entire interval.

Even Bessie has her limitations, though. After being milked during any interval, she must rest R (1 ≤ R ≤ N) hours before she can start milking again. Given Farmer Johns list of intervals, determine the maximum amount of milk that Bessie can produce in the N hours.

Input

* Line 1: Three space-separated integers: NM, and R
* Lines 2..M+1: Line i+1 describes FJ's ith milking interval withthree space-separated integers: starting_houri , ending_houri , and efficiencyi

Output

* Line 1: The maximum number of gallons of milk that Bessie can product in the N hours

输入

12 4 2
1 2 8
10 12 19
3 6 24
7 10 31

输出

43

题目大意:

farmer John 要给牛挤奶。挤奶时间 N (1 ≤ N ≤ 1,000,000) hours,注意Bessie每次挤奶休息完R (1 ≤ R ≤ N)hours后,又可以挤。farmer John 有M个时间段,开始时间s,结束时间e,一旦开始就不能停下,直到挤完奶。在这些时间段里可以给Bessie挤奶,但每个时间段的效率不同,有个挤得多一点,有得少一点。现在你的任务是根据famer john的时间段,选择搭配起来最有效率的时间段来让Bessie产奶最多。

思路:

DP。先将时间以结束时间由小到大排序一遍。dp [ i ] 代表选择第 i 个容器时可以获得的最大产量。所以 dp [ i ] = max (dp [ j ] + cow [ i ].val,dp [ i ] )( j <= i && cow[ j ].End + r <= cow [ i ].Sta )。最后还要算出所有容器 dp 出来的最大值才是答案。初始化时,每个 dp 对应为自身的 val 值,所以 dp [ i ] 代表一定会选择自己本身的这个容器。

为什么要由小到大排序?

因为要最大利用时间,若不排序的话,那么根据判断条件 cow [ j ].End + r <= cow [ i ].Sta,要求的是上一个的结束时间 + 间隙 小于 要该容器的开始时间才能进行更新,不排序的话,那么有些容器就可能会跟新不到了。故要由小到大排序。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<iomanip>
#include<iostream>
#define INF 0x3f3f3f3f
#define MAX 200000
using namespace std;
struct node
{int s,e,w;
}a[1005];
int dp[1005];
bool cmp(node a,node b)
{if(a.s<b.s)return true;if(a.s==b.s&&a.e<b.e)return true;return false;
}
int main()
{int n,m,r;scanf("%d%d%d",&n,&m,&r);for(int i=0;i<m;i++){scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].w);a[i].e+=r;}sort(a,a+m,cmp);int ans=0;for(int i=0;i<m;i++){dp[i]=a[i].w;for(int j=0;j<i;j++){if(a[i].s>=a[j].e)dp[i]=max(dp[i],dp[j]+a[i].w);ans=max(ans,dp[i]);}}printf("%d\n",ans);return 0;
}

补充

背包

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define N 1001
using namespace std;
int m,n;
int w[N],c[N],f[N];
void ZeroOnePack(int cost,int weight)
{for(int v=m;v>=weight;v--){f[v]=max(f[v],f[v-weight]+cost);//cout<<"["<<v<<"]"<<f[v]<<"  ";}cout<<endl;
}int main()
{cin>>m>>n;for(int i=1;i<=n;i++)cin>>w[i]>>c[i];for(int i=1;i<=n;i++)ZeroOnePack(c[i],w[i]);cout<<f[m]<<endl;return 0;
}
【题目描述】
一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn,求旅行者能获得最大总价值。【输入】
第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。【输出】
仅一行,一个数,表示最大总价值。【输入样例】
10 4
2 1
3 3
4 5
7 9
【输出样例】
12
————————————————

完全背包

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define N 1001
using namespace std;
int m,n;
int w[N],c[N],f[N];
void CompletePack(int cost,int weight)
{for(int v=weight;v<=m;v++)f[v]=max(f[v],f[v-weight]+cost);
}int main()
{cin>>m>>n;for(int i=1;i<=n;i++)cin>>w[i]>>c[i];for(int i=1;i<=n;i++)CompletePack(c[i],w[i]);cout<<"max="<<f[m]<<endl;return 0;
}
【题目描述】
设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。【输入】第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。【输出】
仅一行,一个数,表示最大总价值。【输入样例】
10 4
2 1
3 3
4 5
7 9
【输出样例】
max=12

学习感悟

接触动态规划之后感觉直接开了个了不得的新坑,很多思想都是之前没有接触过的,很多方法也需要自己去总结,看了很多东西之后依然感觉自己没有入门,接下来也要继续努力学习这方面的东西。

2020年3月最后一周心得相关推荐

  1. 美学心得(第二百一十七集) 罗国正 (2020年12月)

    美学心得(第二百一十七集) 罗国正 (2020年12月) 2957.我有闲时,找些好诗来读读,并细看诗歌的注释,既是一种美的享受,增长很多语言文化.历史等知识,还经常令我心潮激荡.然后,根据诗的意境和 ...

  2. 10备忘录没有表格_我的投资备忘录(2020年12月04日)

    前言: 首先根据行业搭配.基金优劣等,主要选取"消费.医疗.科技"三个主赛道的优质基金: 其次按照行业景气度.市场热点等,混搭金融地产.军工.有色金属等短线题材基金: 本金分为10 ...

  3. 【读书】2020年阅读记录及心得

    [读书]2020年阅读记录及心得 主要记录个人今年的阅读情况,以及部分带有强烈主观思想的读书笔记输出(按大致的时间顺序). 阅读工具:微信读书(真的很方便).Kindle(有些书微信阅读上没资源,补充 ...

  4. 爆料称macOS Ventura正式版预计将于10月最后一周推出 支持新款14/16英寸MacBook Pro

    据彭博社的 Mark Gurman 的消息,苹果计划在 10 月 24 日到 30 日这一周发布新的 macOS Ventura 和 iPadOS 16 系统. 据称,macOS Ventura 首个 ...

  5. 北风修仙笔记—2020年8月

    HI,欢迎来到北风的修仙笔记. 这里会记录下北风在人生路上升级打怪的一些思考,每月月底都会以本文的形式在公众号集中发布. 当然如果想提前剧透的,可以关注我的知识星球@采铜于山.知乎@北风博客 .微博@ ...

  6. Linux阅码场 - Linux内核月报(2020年12月)

    关于Linux内核月报 Linux阅码场 Linux阅码场内核月报栏目,是汇总当月Linux内核社区最重要的一线开发动态,方便读者们更容易跟踪Linux内核的最前沿发展动向. 限于篇幅,只会对最新技术 ...

  7. 2020 年 5 月程序员工资统计,平均 14542 元,我又拖后腿了!

    点击上方"视学算法",选择加"星标"置顶 重磅干货,第一时间送达 来源/作者:有数可据     转载自:算法爱好者 https://blog.csdn.net/ ...

  8. pve rust 能拆家吗_RUST:2020年9月第四周:向上向上再向上!

    九月第四周,马上就要迎来中秋国庆八天假!昨天被什么秋天第一杯奶茶的梗弄得一愣一愣的今天刚缓过劲来本期内容依旧是围绕了下个月即将上线的电梯展开更多消息被公布,让我们进来看个痛快!RUST:2020年9月 ...

  9. 微型计算机2020年6月上,2020年1-6月全国微型计算机设备产量统计分析

    [中国报告大厅讯]根据中国报告大厅对2020年1-6月全国微型计算机设备产量进行监测统计显示:2020年6月全国微型计算机设备产量3216.5万台,同比增长0.3%,2020年1-6月全国微型计算机设 ...

最新文章

  1. linux系统中使用chattr命令的,chattr命令怎么用
  2. 内置函数、匿名函数,递归函数
  3. 一文读懂密码学中的证书
  4. java socket 路由_JAVA简单的Socket网络编程!CS
  5. DataTables获取指定元素的行数据
  6. stringutils 用哪个包 apache spring_spring整合mq、jsonp跨越、httpclient工具的使用
  7. 对话框应用程序的DoModal()源代码
  8. postgres触发器使用
  9. boot spring 启动 文本_SpringBoot启动时如何加载配置文件
  10. 【C语言】科学计数法——复习总结
  11. 人工智能是在数学计算机科学控制论信息论,ai人工智能需要学什么 人工智能对数学有何要求...
  12. sun存储的串口连接管理_修改SUN设备管理IP的步骤
  13. 学校生均计算机台数统计表,学校计算机数量名称、型号、数量、发布情况统计表...
  14. android学习笔记之磁场传感器制做指南针
  15. 【欧拉计划第 5 题】最小公倍数 Smallest multiple
  16. python利用正则爬取内涵段子内容
  17. Win11开机提示音要怎么改?
  18. nvidia账号、cuDNN的下载账号分享
  19. 2.淘宝店铺轮播图装修方法代码
  20. 代码随想录训练营day29

热门文章

  1. 下级对上级回复已阅知_下级对上级回复已阅知_工作中回复领导,绝不能用OK!除此之外,还有四条...
  2. Spring Boot @EnableAutoConfiguration解析
  3. 2017年GitHub中最为流行的30个开源机器学习项目
  4. python的allure使用
  5. 对于SLAM定位中各类坐标系的理解(坐标系,里程计坐标系,基座坐标系与雷达坐标系)
  6. supervisord
  7. Julia是什么?为什么突然这么火?
  8. 第三章:可行性研究及需求分析
  9. jotform 设计器_使用JotForm 4.0减轻表单构建的痛苦
  10. 为什么大部分公司的数据库系统仍然要使用oracle?