ccpc河北大学生程序设计竞赛dp小总结

近期题目来自校赛,赛前训练,省赛热身,河北ccpc正式比赛。

题目一:

题目描述:

由于第m个台阶上有好吃的薯条,所以薯片现在要爬一段m阶的楼梯.
薯片每步最多能爬k个阶梯,但是每到了第i个台阶,薯片身上的糖果都会掉落ai个,现在问你薯片至少得掉多少糖果才能得到薯条?

输入:

多组数据输入,每组数据第一行输入两个数字m(1<m<=1000),k(1<=k<m),接下来有m行,每一行输入ai(0<ai<=1000),表示第i个台阶会掉落的糖果.

输出:

对于每组数据,输出至少要牺牲的糖果数.

样例输入

5 2
1 2 3 4 5
6 2
6 5 4 3 2 1

样例输出

9
9

分析:经过的数字全部加起来,为一个累加和,求最小累加和

递推关系:

定义f(n)为必须到第n个台阶的最少累加和

分析可以如何得到f(n),我们通过跳一步,可以怎么跳到第n个台阶呢?

可以从第n-1个台阶跳到这里,可以n-2,n-3......n-k。

也就是说,

f(n)=an+min(f(n-1),f(n-2),......f(n-k))

必须到第n个台阶的最少累加和,就等于能跳到这里的所有位置中,最小的那个f(),跳过来(也就是加上本身)。

注意:前k个台阶可以从起点直接跳过来,贪心思想,经过任何多余的数字都不会是最优解。所以前k个f(n)直接赋值an.

也可以维持单调队列把时间降到线性,不过o(n*k)已经足够过了。

 

题目二:

题目描述:

JiangYu的小金库是一个三维立体的空间,大小为XYZ,里面每个位置都藏着各种价值的宝物,既然是宝物价值自然非同一般,可正可负。

可恶的花花得知了这一切,想要偷走其中的珍宝们。

可是Jiangyu的小金库安保措施十分严密,花花只有一次行动的机会,他决定偷走一个价值尽可能大的长方体区间。

那么他最大能偷走多少钱的宝物呢?

输入:

第一行给出三个正整数 X,Y,Z

第二行一个整数n, 宝藏的数量

接下来n行,每行给出一个宝藏的位置xi,yi,zi, 以及价值ci

保证宝藏位置不重复。 (1 \leq X,Y,Z \leq 201≤X,Y,Z≤20)

(1 \leq n \leq X \times Y \times Z1≤n≤X×Y×Z)

(1 \leq xi \leq X1≤xi≤X)

(1 \leq yi \leq Y1≤yi≤Y)

(1 \leq zi \leq Z1≤zi≤Z)

(-1e9 \leq ci \leq 1e9−1e9≤ci≤1e9)

输出:

一个整数,最大的价值

样例输入

2 2 2
8
1 1 1 10
1 1 2 9
1 2 1 10
1 2 2 9
2 1 1 10
2 1 2 9
2 2 1 -1
2 2 2 10

样例输出

66

 

https://blog.csdn.net/hebtu666/article/details/82788866这个网址写了详细讲解哦。。。最好要看看

首先要明白一维最大子数组问题,设dp[n]的含义为必须以an结尾的数组中的最大和。

所以dp[n]就是,每一个以在n前面的结尾的最大值,加上an.

二维方法:转化为一维来做。枚举长度为原矩阵长度的所有矩阵。然后压成一维来做。

时间:

因为有n个开头,每个开头有n-1,n-2......1个结尾,所以枚举的时间复杂度为o(n^2)。

为了节省时间,利用预处理数组思想,定义长宽和原矩阵一样的矩阵gg。

每列满足第n列k行的值为sum(l[0][n]+l[1][n]....l[k][n]),可以o(n*m)做到(nm为长宽).然后枚举到某矩阵的时候直接根据gg得出。整体做到o(n^2)枚举并求和。然后按一维做。整体o(n^3)

三维:并没有什么高大上的优化,也是枚举每一个长宽固定的长方体,压缩至二维,然后按二维做。

 

题目三:

热身赛,并没有原题,手打。

过的队伍不多

一种动物,出生到死亡只有三年,即n年出生,n+3年死去。

出生一年以后可以生育,也就是n+1年开始生育,一年可以生一只宝宝。

定义第n年动物总数为an,给定n,返回an/a(n-1),最多保存小数点后十位

第一年有一只

思路一:定义f(n)为第n年新出生的动物个数,则f(n)=f(n-1)+f(n-2),前两项为1,而每年的总数也就是三项求和而已。

每年出生的数量为1,1,2,3,5,8,13,21

每年总数就是1,2,4,10,16,26,42

发现是斐波那契数列

思路二:直接从总数入手,定义f(n)为第n年的总数

如何求出an/a(n-1):要看有多少动物能活到n年,活不到n年的也不能在第n年生育,活到n年的动物每人生一个,所以an就是二倍的能活到n年的动物。求此数方法很多,在此只说一个:

f(n-1)-(1/2)f(n-3)

去年的数量减去,去年还活着的今年就死了的数量。

这个数乘二,得出答案f(n)=2f(n-1)-f(n-3),其实本质还是斐波那契,因为f(n-1)=f(n-2)+f(n-3),带入以后发现f(n)=f(n-1)+f(n-2)。

式子写出来了,但是原题数据范围是10^1000,不能一项一项推过去。

尝试发现,几十项之后,an/a(n-1)的十位小数之内都没有变过,所以当数字较大时直接输出第五十项即可。

本题结束

但是还有点别的东西想写

 

斐波那契的美

万物之美,总能找到斐波那契数列的规律。随着n的增加,an/a(n-1)越来越接近黄金分割

手写了求解过程。可能写的不规范,但是就是表达这个意思。

 

只要数列满足X(n) = X(n-1) + X(n-2),无论前两个值是多少,都满足黄金分割的条件,而斐波那契数列是最简单的特例:前两个元素均为1

数学家还发现了费马大定理和这个数列的关系(费马大定理的证明,三百五十年),并应用到诸多领域(比如加密)。有兴趣自行了解。

 

题目四:

省赛,没有原题。十六支队伍过了这个题。

https://blog.csdn.net/hebtu666/article/details/79964233

参考我前面的文章,dp入门篇,那个会了这个就会。

参考萌新题

现场因为对c++不熟,没敢压空间,规规矩矩的写了一遍,还因为多打了一行罚了时,跟智障一样。。。

 

 

题目五

http://newoj.acmclub.cn/contests/1359/problem/6

题意:最长公共子序列,要求序列每个元素重复k次,比如1122重复两次,111222重复三次。

输入两个字符串和k,输出长度。

最长公共子序列的一个变形。。。

动态规划。设dp[i][j]表示a串处理到i位置,b串处理到j位置的答案。预处理出从a串i位置向前数,第k个与i位置数
字相同的位置p[i],用相同方式处理出B串的q[i]。
则转移方程为dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-p[i]][j-q[j]]+1),其中第三种转移必须在a[i]=b[j]的情况下转移。

 

#include <bits/stdc++.h>
using namespace std;
int k,n,m,dp[1005][1005];
int a[1005],b[1005];
int pa[1005]={0},pb[1005]={0};
queue<int> q[1005];
int main()
{int ak; cin>>ak;while(ak--){for(int i=1;i<=n;i++)while(!q[i].empty()) q[i].pop();scanf("%d%d%d",&k,&n,&m);memset(dp,0,sizeof(dp));memset(pa,0,sizeof(pa));memset(pb,0,sizeof(pb));for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=m;i++) cin>>b[i];for(int i=1;i<=n;i++){q[a[i]].push(i);if(q[a[i]].size()==k){pa[i]=q[a[i]].front();q[a[i]].pop();}}for(int i=1;i<=n;i++)while(!q[i].empty()) q[i].pop();for(int i=1;i<=m;i++){q[b[i]].push(i);if(q[b[i]].size()==k){pb[i]=q[b[i]].front();q[b[i]].pop();}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){dp[i][j]=max(dp[i-1][j],dp[i][j-1]);if(a[i]==b[j] && pa[i]!=0 && pb[j]!=0)dp[i][j]=dp[pa[i]-1][pb[j]-1]+k;}}printf("%d\n",dp[n][m]);}return 0;
}

代码都是比赛时候写的,真的不想找来贴了。

 

最后总结经验教训:

 

注意细节,注意细节,注意细节

多种思路,多种思路,多种思路

递归关系自己推,比如背包,你要是看套路。。。Emmm。。就连套路都不会用了。

平时递归关系自己推,自己推,自己推。

 

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

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

相关文章

c语言简便实现链表增删改查

注&#xff1a;单追求代码简洁&#xff0c;所以写法可能有点不标准。 //第一次拿c开始写数据结构&#xff0c;因为自己写的&#xff0c;追求代码量少&#xff0c;和学院ppt不太一样。有错请指出 #include <stdio.h> #include <stdlib.h> #include <string.h>…

第一次课 课上代码

第一次课内容 学习心态及注意事项 信心 谦虚 脚踏实地 多动手 python简介 代码量少&#xff0c;简介&#xff0c;易上手&#xff0c;语法要求不过于严格&#xff0c; Python 库。 速度慢&#xff0c; 不可加密。 输出、变量、输入 数据类型&#xff1a;整数、浮点数…

计算机考研专业课只考一科的学校汇总

下列学校专业课只考1门 &#xff08;每项科目下的学校均按照最新学科评估结果由高到低进行排名&#xff09; C语言程序设计 1. 湖南大学 计算机技术&软工专硕&#xff08;信息科学与工程学院&#xff09; 2. 中国海洋大学 计算机技术&#xff08;01计算机应用技术方向&am…

数组实现栈

学习了改进&#xff0c;利用define typedef比上次写的链表更容易改变功能&#xff0c;方便维护&#xff0c;代码更健壮。 大佬别嫌弃&#xff0c;萌新总是很笨&#xff0c;用typedef都想不到。 #include<stdio.h> #include<stdbool.h> #define maxsize 10 typede…

简单暴力到dp的优化(中级篇)

下面再放三道我比较喜欢的&#xff0c;需要好好写一下的题。 第一题比较水 1. White Cloud is exercising in the playground. White Cloud can walk 1 meters or run k meters per second. Since White Cloud is tired,it cant run for two or more continuous seconds. Whi…

第二次课 课上代码

敲一遍&#xff0c;体会每行代码想表达的意思。 第二讲 创建.py文件 数据类型&#xff1a;布尔(and\or\not) 条件判断语句(if elif else) 列表基础操作&#xff08;特点、创建、增加元素、len()、下标、py切片&#xff09; >>> 5>4 True >>> 4>5 Fa…

第一次课 优秀作业展示

18级河北师大软件编程训练 很多同学非常认真的完成了作业&#xff0c;这里选出比较优秀的作业展示出来。 注&#xff1a;展示顺序不是排名 为了尊重同学们的劳动成果&#xff0c;并没有要代码&#xff0c;只是截图展示。 范天祚 &#xff08;傻兔子&#xff09; 熊静祎&…

dp打开思路:HDU1029 HDU1087 HDU1176 HDU1257 POJ1458(水题不水)

题目&#xff1a;https://vjudge.net/contest/68966#overview HDU - 1029 题意&#xff1a;找出出现次数超过一半的数字 蠢思路&#xff1a;排序找中间 DP&#xff1a;扫一遍一个变量count记录解出现的次数&#xff0c;是当前解就&#xff0c;否则--&#xff0c;count为负就…

dp打开思路2:POJ2533 HDU1114 HDU1260 HDU1160(水题不水)

题目&#xff1a;https://vjudge.net/contest/68966#overview POJ2533 最长上升子序列&#xff0c;很平常的题&#xff0c;但是维持单调队列二分还是值得一贴的&#xff0c;O(nlogn) 关键思想&#xff1a;出现在单调队列里的数都在当前接收的数之前&#xff0c;所以找到最小…

二分查找及一般拓展总结

二分-不止是查找哦 二分过程&#xff1a;首先&#xff0c;假设表中元素是按升序排列&#xff0c;将表中间位置记录的关键字与查找关键字比较&#xff0c;如果两者相等&#xff0c;则查找成功&#xff1b;否则利用中间位置记录将表分成前、后两个子表&#xff0c;如果中间位置记…

第三次课 课上代码

这次可能比较简短&#xff0c;这样也好&#xff0c;可读性比较强。 别问我为什么&#xff0c;我不会告诉你们我把代码关了的哼哼。 简单复习、注意事项及小知识强调讲解 作业讲解 列表的遍历 For循环&#xff08;这个参考切片&#xff0c;视频有详细讲解&#xff0c;一样的…

排序算法基本介绍及python实现(含详细注释)

对数组排序可以说是编程基础中的基础&#xff0c;本文对八种排序方法做简要介绍并用python实现。 代码中注释很全&#xff0c;适合复习和萌新学习。这是刚入学自己写的&#xff0c;可能难免比不上标准的写法&#xff0c;但是懒得改了。 文末会放和排序相关的基本拓展总结链接…

第二次作业 讲解及展示

第二次作业&#xff0c;同学们虽然在认真完成&#xff0c;但是或多或少都出了一些错误&#xff0c;一班张婷&#xff0c;四班武仪人&#xff0c;六班杨泽宇&#xff0c;八班候雯洁&#xff0c;安锦阳&#xff0c;刘净圆&#xff0c;这些同学完成的较为出色&#xff0c;错误较少…

深搜DFS\广搜BFS 图初步入门

首先&#xff0c;不管是BFS还是DFS&#xff0c;由于时间和空间的局限性&#xff0c;它们只能解决数据量比较小的问题。 深搜&#xff0c;顾名思义&#xff0c;它从某个状态开始&#xff0c;不断的转移状态&#xff0c;直到无法转移&#xff0c;然后退回到上一步的状态&#xf…

素数基本(埃氏筛法/线性筛法)

一、检查n是否为素数 最简单思路&#xff1a;所有可能的因数全部试一遍。 int gg(int n) {for(int i2;i<n;i){if((n%i)0)return 0;//有因数就不是素数咯}return 1; } 进一步思考&#xff1a;没必要枚举所有的数&#xff0c;每一个小于n^(1/2)的因数i&#xff0c;一定有一个大…

欧几里得gcd/extend_gcd

正式叙述前还写了一点自己的小感受。 问题&#xff1a;求两个正整数a&#xff0c;b的最大公约数。 大神看来是很简单的问题&#xff0c;但是对于去年夏天刚学python的我来说&#xff0c;这是个很难的问题&#xff0c;还记得当时一晚上睡不着都在想怎么快一点的求出最大公约数…

python基础技巧总结(一)

最近总结一下python基础知识&#xff0c;就暂时弃坑了。 本文总结只属于python的一些骚操作。。。 后面文章自行去博客学习交流 原地交换 Python 提供了一个直观的在一行代码中赋值与交换&#xff08;变量值&#xff09;的方法 x, y 10, 20 print(x, y)x, y y, x print(x…

python基础技巧总结(二)

一总结的链接&#xff1a; 好&#xff0c;我们继续 一次性初始化多个变量 可以直接赋值&#xff1a; a,b,c,d1,2,3,4 可以利用列表&#xff1a; List [1,2,3] x,y,zList print(x, y, z) #-> 1 2 3 &#xff08;元素个数应与列表长度相同&#xff09; 打印模块路径 im…

python基础技巧总结(三)

前两篇文章&#xff1a; https://blog.csdn.net/hebtu666/article/details/81698235 https://blog.csdn.net/hebtu666/article/details/81698329 我们继续总结&#xff1a; 开启文件分享 Python 允许运行一个 HTTP 服务器来从根路径共享文件&#xff0c;下面是开启服务器的…

python基础技巧总结(四)

前三期请到我博客里找 https://blog.csdn.net/hebtu666 我们继续总结 except的用法和作用 try/except: 捕捉由PYTHON自身或写程序过程中引发的异常并恢复 except: 捕捉所有其他异常 except name: 只捕捉特定的异常 except name, value: 捕捉异常及格外的数据(实例) exce…