总结(ACM选修课结课总结)!

总结:

这门选修课虽然结课了,但路还没有走完,还有很多知识没学,继续前进吧。
以下是大致我写的目录:
一、 学到了什么;
二、学会了那些;
三、掌握了那些、哪些方面有提升。
四、自己的感受。

开始:

一: 这要从头开始说了:
一开始讲了 STL上的 比较常用的容器;
在之后一直到结课 就是算法的内容了;
大致是:贪心算法(基本贪心、背包、两种优先级贪心)、动态规划(线性dp、区间dp、背包问题)、二分三分法、搜索(DFS,BFS)。

二:
1、首先当然是容器了:
vector,当需要使用动态数组的情况下,可以考虑使用vector。
栈(stack) 先进后出;
队列(queue) 先进先出;
优先队列 (priority_queue) 最大自动移到队首;
set ,快速检索,去重与排序。
map 自定义键和值 类似数组,有清晰的一对一关系。
应用:
1、 去重:利用映射的一一对应性,把可能出现重复的数据设置为key值以达到去重的目的。
2、排序:自定义Compare类
unique 去重;
都需要导入本名头文件。

2、 开始了;贪心算法:
只在局部考虑最优,不在整体上考虑最优解。
①贪心选择性质:
在求解一个问题的过程中,如果在每一个阶段的选择都是当前状态下的最优选择,即局部最优选择,并且最终能够求得问题的整体最优解,那么说明这个问题可以通过贪心选择来求解,这时就说明此问题具有贪心选择性质。
②最优子结构性质:
当一个问题的最优解包含了这个问题的子问题的最优解时,就说明该问题具有最优子结构
大致步骤:
找准 优先变量 sort()函数 一排序 哎 就出来了。
排一次不行 就排两次 ; 最后再看看能不能优化一下,节省点空间,时间。
要是还不行,就别贪心了,换个方法吧。
3、动态规划:
(动态规划是分阶段求最优值的算法。)
将复杂问题按阶段划分成子问题;
枚举子问题各种可能情况,从中找出最优值;
利用子问题的最优值求得源问题的最优解

大致思想:就是用一维数组或者二维数组,记录状态(自定义)(历史记录),然后运用状态转移方程得出来每个子问题的状态,最后找最优解。(一般状态转移方程是根据:递推算法或者递归算法 定义。)
一般步骤:
(1)、判断问题是否具有最优子结构性质,若不具备则不能用动态规划。
(2)、把问题分成若干个子问题(分阶段)。
(3)、建立状态转移方程(递推公式)。
(4)、找出边界条件。
(5)、将已知边界值带入方程。
(6)、递推求解。
还有方法因题而异,多刷刷题才更熟练。
动态规划背包问题(四种类型:1、01背包;二、完全背包;三、多重背包;四、分组的背包问题。)
(1)、 01背包;
(物品选不选,物品只能用一次。)
问题描述:有N件物品和一个容量为V的背包。第i件物品的费用(即体积,下同)是w[i],价值是val[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

解题思路:用动态规划的思路,阶段就是“物品的件数”,状态就是“背包剩下的容量”,那么很显然dp[ i , v ] 就设为从前 i 件物品中选择放入容量为 v 的背包最大的价值。那么状态转移方程为:

dp[i][v]=max( dp[i-1][v],dp[i-1][v-w[i]]+val[i]

这个方程可以如下解释:只考虑子问题“将前 i 个物品放入容量为 v 的背包中的最大价值”那么考虑如果不放入 i ,最大价值就和 i 无关,就是 dp[ i - 1 ][ v ] , 如果放入第 i 个物品,价值就是 dp[ i - 1][ v - w[i] ] + val[ i ],我们只需取最大值即可。
(2)、完全背包。
(物品无限选)。
问题描述:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是w[i],价值是val[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

解题思路:完全背包问题与0/1背包问题不同之处在于其每个物品是无限的,从每种物品的角度考虑,与它相关的策略就变成了取0件、1件、2件…。我们可以根据0/1背包的思路,对状态转移方程进行改进,令f[i][v]表示前 i 种物品恰放入一个容量为 v 的背包的最大权值。状态转移方程就变成了:

f[i][v]=max(f[i-1][v],f[i][v-w[i]]+val[i])

我们通过对0/1背包的思路加以改进,就得到了完全背包的一种解法,这种解法时间复杂度为O(n^3), 空间复杂度 为O (n^2)。
(3)、 多重背包;
(物品选有限次。)

问题描述: 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件占空间是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
思路算法: 多重背包中的每种物品的数目有一定的界限n[i] ,每种物品可以放0个,1个…n[i]个。与完全背包类似,定义子结构f[i][v]表示前i种物品恰好装入背包容量是v的最大价值。那么它的状态转移方程为:

f[i][v] = max{f[i-1][v-kc[i]]+kw[i] | 0 <= k <= n[i]}

复杂度为O(V*∑n[i])。
转化为01背包求解,就是将第i种物品分成n[i]件01背包中的物品。得到了物品数是∑n[i]件的01背包。(定义一个结构体数组 输入c,w,n)
二进制思想优化:
利用的是二进制的思想。就是将第i种物品分成若干件物品,其中每件物品都有一个系数,这件物品的费用和价值都是原来的费用和价值乘以这个系数。这些系数分别是1,2,4…2(k-1),n[i]-2(k)+1,其中k是满足n[i]-2^k+1>0的最大整数。
例如原来n[i] = 13,那么该种物品可以拆分成4种物品,其系数分别1,2,4,6。而且可以证明小于等于n[i]的任何数目的物品都可以由拆分后物品的和组成。这样就减低了复杂度。
(4)、分组背包问题。
问题描述:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
算法思路:
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值
状态方程:

f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]| 物品i属于组k}

4、二分三分法:(快速确定答案)
二分:
简单定义:在一个单调有序的集合中查找元素,每次将集合分为左右两部分,判断解在哪个部分中并调整集合上下界,重复直到找到目标元素。 时间复杂度:O (logn),优于直接顺序查找O(n)
代码: (记住,一定要有序序列

double end,start,mid;
while(end - start > 1.0e-6)
{
	 mid = (start+ end)/2;
    if(Caculate(mid)<x)
        start=mid;
    else
        end=mid;
}

三分:
当需要求某凸性或凹形函数的极值,通过函数本身表达式并不容易求解时,就可以用三分法不断逼近求解。
定义:
类似二分的定义Left和Right
mid = (Left + Right) / 2
midmid = (mid + Right) / 2;
如果mid靠近极值点,则Right = midmid;
否则(即midmid靠近极值点),则Left = mid;

5、搜索:
在讲之前老师先讲了一下递归算法,就是层层分解的算法思想,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
最后到最小问题时直接求解。
递归的步骤:
1、找出大规模问题与小规模问题之间的关系,这样通过递归使问题的规模逐渐变小。
2、设置边界、控制递归。
3、设计函数、确定参数。

之后开始讲搜索:

基本概念: 搜索算法是利用计算机的高性能来有目的地穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法,相比于单纯的枚举有一定的方向性和目标性。
状态: 状态(state)是对问题在某一时刻进展情况的数学描述,或者是数学抽象。

状态转移: 每一个状态都会是答案的一个“可能的”解。状态的转移就是问题从一个状态转移到另一个状态,这样就可以进行搜索的一步步延伸,最后要得到的解也是其中的一个状态。
进行状态转移的方法:
(1)、深度优先搜索 (DFS) (2)、广度优先搜索(BFS)
搜索适用范围:
下一个可能为终点的点可以由目前已经找到的点通过若干种方式递推得到,且递推的方式一般为有限个。
(1)、深度优先搜索(DFS)
基本思想:
从初始状态,利用规则生成搜索树下一层任一个结点,检查是否出现目标状态,若未出现,以此状态利用规则生成再下一层任一个结点,再检查,重复过程一直到叶节点(即不能再生成新状态节点),当它仍不是目标状态时,回溯到上一层结果,取另一可能扩展搜索的分支。采用相同办法一直进行下去,直到找到目标状态为止。
(就像认准一条路,往死里磕,这条路不对,就往回走换条路继续磕,直到找到正确的。)
(2)、广度优先搜索(BFS)
基本思想:从初始状态S 开始,利用规则,生成所有可能的状态。构成的下一层节点,检查是否出现目标状态G,若未出现,就对该层所有状态节点,分别顺序利用规则。
生成再下一层的所有状态节点,对这一层的所有状态节点检查是否出现G,若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开。直到出现目标状态为止。
(这个就像先把所有的第一步按顺序都走一遍,然后第二步一样,直到找出正确答案。)

三、
我的掌握:
刚开始的那几周,那时候因为几乎没有其他的课程压力。所以学习这门课的时间较为充裕。对贪心算法,线性dp,区间dp记得都比较牢固,到了二分以后,时间比较紧张。二分三分搜索就相对不熟练。但总体来说,我的写代码能力比选课之前来说可谓是提升了不止一大截,遇到题的反应速度和思维深度也提升了不少。
再说codeforces:
刚开始接触这个网站的时候,看见全英文马上感觉头就很大,因为我英语不好。第一次比赛是div3的难度,我那是一个多小时才出题a题最后结束也才出两题。打比赛的时候脑子老是不冷静,代码老是写不对,代码漏洞百出。之后就意识到这个问题,每次比赛都先提前冷静一会,把脑袋放空。比赛过后题目看看大佬是怎么想问题的,他们的思考路线是怎么走的,总结前几个题目的规律。我目前得出abc的题目就是思维题思考方向就是找特殊点,简单的数学逻辑问题。而在这之后打比赛,A题从一开始的时候一个多小时到现在的最快十分钟。一局比赛最起码能做两三道。题目理解能力上升了,写代码的方法,技巧和花样也多了起来。总之实力提升了不少。从开课到现在,我也打了十几场比赛了,还没有到达入门水平,还得继续努力。
还有提高了自己学习专注度。平常每天都会有较多的剩余时间,没选这个课程之前,没事情干就会去刷刷B站和玩玩游戏,根本不会去想着系统学习。没结课之前,几乎没有碰过了。剩余时间都是在做老师发的题目,每天投入至少三到四个小时。后来由于因为要打比赛,基本都是十点半开始,要花两到两个半的时间去打比赛。

然后就是CSDN上的总结,虽然老师要求了九周的博客总结,但我从第二周开讲开始每一周都坚持写博客。这不仅加深了我对课上老师讲的内容的理解,而且我还能定期复习,不用费很大的劲来找材料了,并且还能分享给CSDN上其他的小伙伴,何乐而不为呐?
提升自主学习能力和加大自己的知识面广度。老师上课讲的有些听懂了但是一写就废,有些听不懂还得自己去查资料思考,盯着ppt看半天,还有老师出的题目有些还是有课上没有讲到的知识点,还有打CF比赛补题目时所遇到的知识点,所以大部分是在边做题边学习,大多数还是自主学习。在没有参加这个课程之前,我只知道c++基础的知识,如果没有参加这个课程我可能还停留在冒泡排序,双重循环,程序设计等等这些层面。之前根本不知道CF,牛客,Atcoder这些比赛网站,连网站都不知道更别说去打比赛提升自己了。
这一百多天走过来,虽然与当初自己的豪情壮志渐行渐远,但是这其中确实锻炼了我的思维能力,明白了一些算法也确实提高了我的编程能力,我觉的这就是收获。
ACM这门课对我的提升非常之大。不仅增强了我的专业知识,提升了我的专业技能,还增强了我的学习能力,找资源能力,知道怎样更加全面的学会一个知识。

为我的未来添砖加瓦。(老师用心良苦)

四、

感受:
回想,老师把这门课安排进了计算机类所有学生课表中,然后说不想上可以取消,不选,我眼看我身边的人一个个一个个的取消, 一开始我是抱着强烈的好奇心和兴趣没有取消这门选修课,但我心里还是挺庞然的,刚开始上课有很多人,大部分都是来旁听的,但是越往后,剩下的几乎就是我们这些选课的了 。果然没选课没压力就没有动力。而且这门课对我受益匪浅,最后事实证明我的选择没有问题。
报名ACM选修课我最初的目的就是就是提升自己,通过努力学习,参加竞赛。做一件事要善始善终,不能半途而废,既然我已经做出了自己的选择就不会轻言放弃。第一,我一定会坚持下去,尽最大的努力,学尽可能多的有用的知识。其次,对于我自己的选择,对于自己的学业,我一定会认真对待,认真学习消化知识,做题,定期进行专题总结,本着对自己负责的态度,认真完成每次任务。
说实话,这门课花的时间时挺多的,要一直坚持下去,每天都要经受打击。幸好我还能挺住,到结课了还没有掉队,挺好的。再回首前面这几个月的学习,我挺喜欢我这种求知的冲劲,受挫折不挫败的韧性,沉默不言做事的性格。费老给予的强大压力转化的动力促使我要不断向前。我还记得和同学一起做题,有过为了一道题憋了半天的这种经历很难忘。
越是泥泞的道路,越是容易开出花来。因为你曾经走过的那些路,吃过的那些苦,最终都会在时光的打磨下逐渐发酵,变成营养丰富的土壤,而这种土壤,最适合花开。 所有你流过的泪,是一条渡你的河。所有你受过的苦,将照亮你前方的路。岁月从来没有放过我们,我们亦不能辜负岁月。
还是那句话:ACM课程结束了,但对于算法知识的学习之路还远远没有结束。
🆗

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值