ACM课程总结

时间过的很快,ACM课程在这十几周的时间里就结束了,学了很多的知识,但是只是学了,还没有掌握,做的题太少了,不过也算是圆满的落下了帷幕。
最开始接触acm的时候是专业社团宣传,当时有acm队的学长学姐来给我们讲关于acm的事情,初入大学面对一切都很好奇,当时感觉acm这个东西很厉害,就加入了社团,每周六周末都会有学长学姐抽时间来给我们讲课,为我们学习算法打基础,我还记得最开始的时候第一节课来了很多的人,但慢慢的随着讲得东西变难,有的同学就跟不上上课的速度,每次课都会少一部分人。还有一次举办的acm的新生赛,成绩还不错,当时获得的金牌,给了我很大继续学习acm的信心,再到后来给我们布置的作业,在信息学奥赛一本通上的题,最开始的题很简单,但在寒假训练的时候,开始做一些关于算法的专题,变得难了起来,特别是在dp和被背包这个地方,信息学奥赛一本通的专题做完后,又在vj上专门弄了训练专题。后来到了acm课程开课,有些也都退了这门课,从最初的八十多人到现在的三十来人,我们宿舍有三个人报的这门课,另外两人中一个退的时候,我也有退的想法,感觉这门课太难了,还要刷好多的题,但是又想了坚持了半年多了,寒假训练的时候还做了那么多的题,感觉有点可惜,也就坚持了下来,在codeforces有比赛时,打一打dive2和dive3的比赛,ac的时候真的很有成就感,虽然开始时一直在掉分,到后来才有上分的时候,慢慢的我在寒假训练群里的训练也开始跟不上,两边的题挺多有些做不过来,也就退出了那个寒假训练的群,专心学acm课上的知识,这门课程上课的时候我是听得懂的,但是一到自己做题的时候就会觉得有些困难,而且有些地方不是很好理解,比较绕,做题的时候也存在无从下手的感觉,不知道应该用哪个算法去做,。
这门课不仅教授了算法的知识,并且这门课程也让我养成了写博客的习惯,去刷题的习惯。
总结这个学期学习的过得知识
1.递归算法
首先,分解子问题,将大问题分解成子问题作为递归项来进行递归。

第一步原理,在做递归时,第一步很重要,将第一步与其他步骤分为两类。将子问题变成与大问题形式相同,规模缩小的问题,形成递归。

其次,找到子问题与大问题之间关系,形成递归表达式。

最后,为防止无穷递归,需给出边界条件,当传入的递归项为零时返回值,既作为边界,又作为递归算法每次递归的结果。

2.贪心算法
首先,介绍一下贪心算法专题,贪心算法的基本思想是总是做出在当前看来是最优的选择,即找出整体当前中每个小的局部的最优解,并且将所有的这些局部最优解合起来形成整体上的一个最优解,也就是说贪心算法并不是从整体最优考虑的,它所做出的选择只是在某种意义上的局部最优选择,能够使用贪心算法的问题必须满足下面两个性质:

1:整体的最优解,可以通过局部最优解得出。
2:一个整体可以分割成多个部分,每一部分都可以生成一个最优解。
从贪心算法的定义可以看出,贪心算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。

比如活动安排问题,即有许多个活动,每个活动都有一定的时间,在一个时间轴上,每个活动的开始时间,结束时间都不同,问如何安排活动才能可以看到参加到的活动?这个问题是贪心算法入门的基础题,每个活动都是整体的一部分,如何筛选那?我们可以整理一下每个活动的开始时间进行排序,然后比较第一个活动的结束时间跟下一个活动的开始时间以及结束时间如果下一个活动的开始时间大于第一个的结束,则可以,或者下一个活动的结束小于第一个活动的结束,那就将第二个活动安排为第一舍弃第一个活动,一次类推,每个局部进行比较,以此下去局部最优就是整体最优!
3.动态规划
动态规划有三个最基本的元素:最优子结构、状态转移方程和边界。状态转移方程用于描述将当前状态的解分解为更小状态的关系式;边界即状态转移方程的截止条件;最优子结构即确保通过状态转移方程所选择的子问题也能给出最优的解。
动态规划问题的一般解题步骤
1、判断问题是否具有最优子结构性质,若不具备则不能用动态规划。
2、把问题分成若干个子问题(分阶段)。
3、建立状态转移方程(递推公式)。
4、找出边界条件。
5、将已知边界值带入方程。
6、递推求解。
以最最基础的fibnacci问题为例:其基础的递推关系式为:


4.背包
背包,它主要分为01背包,完全背包和多重背包。
1
01背包的状态转移方程为
f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[j])

i代表对i件物体做决策,有两种方式—放入背包和不放入背包。
j表示当前背包剩余的容量。

转移方程的解释:
创建一个状态矩阵f,横坐标 i 是物体编号,纵坐标 j 为背包容量。
首先将 f 第0行和第0列初始化为0 (代码里面将整个f初始化为0了,其实只初始化第0行和第0列就够了)。这个表示不放物体时最大价值为0 。(物体编号从1开始)
如果背包装得下当前的物体,在遍历过程中分别计算第i件物体放入和不放入背包的价值,取其中大的做为当前的最大价值。
如果背包装不下当前物体那么第i个物体只有不放入背包一种选择。

不放入背包时:第i次决策后的最大价值和第i-1次决策时候的价值是一样的(还是原来的那些物体,没多没少)。
放入背包时:第i次决策后的价值为 第i-1次决策时候的价值 加上 当前物体的价值v[j]。物体放入背包后会使背包容量变为 j ,即没放物体之前背包的容量为j - w[i]。
2
完全背包问题的特点是,每种物品可以无限制的重复使用,可以选择放或不放
其状态转移方程为:
dp[i + 1][j] = max(dp[i][j], dp[i][j - k * A[i]] + k * V[i])
借用01背包的思想,本次使用的转移方程也是只涉及到i-1的纵向级别。但与上面不同的是,此次考虑的对象是dp[i][j-v[i]],所以我们必须让体积由前向后循环:
for(int i=1->n)
for(int j=1->v)
dp[j]=max(dp[j],dp[j-v[i]]+w[i])。
3
有N种物品和一个体积为V的背包。第i种物品最多有n[i]件可用,每件体积是w[i],价值是v[i]。将哪些物品装入背包可使这些物品的体积总和不超过背包体积,且价值总和最大?
dp[i][j]表示前i种物品放入体积为j的背包中的最大价值。
状态转移方程:
dp[i][j] = max{ f[i-1][j - kw[i]] + kv[i]},0 <= k <= n[i]
完全按照此思路,代码为三层循环,复杂度达 O(NVΣni)。可以和完全背包一样,借鉴01背包的思想,进行优化。
它的问题的思路跟完全背包的思路非常类似,只是k的取值是有限制的,但是每件物品的数量是有限制的。
其中c[i]是物品的数量,和完全背包的不同支出在于完全背包可以取无数件,而多重背包给定了最多能取的数量。这样也是三个循环,分别是背包容量,物品个数和物品种类。
5.二分和三分
这部分算法理解起来比较容易,并且在查找元素的时候可以提高很高的效率。并且扩展出去知道问题解得范围,并且有单调性,可以不断地二分验证求出答案。最典型的就是切绳子问题,n条切成k段,最长的长度是多少。思路就是是在某一区间内查找元素,如果查找到了元素,结束;如果未查找到,目标元素在左边,更改上界,目标元素在右边,更改下界,知道找到或者逼近为止。对于二分三分的总结就是:对于一些实际问题,当公式难以推导出来时,二分、三分法可以较为精确地求解出一些临界值,例如一些函数的极大值,极小值。

1二分法
当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。
基本思想:假设数据是按升序排序的,对于给定值key,从序列的中间位置k开始比较,
如果当前位置 arr[k] 值等于key,则查找成功;
若 key小于当前位置值arr[k],则在数列的前半段中查找,arr[low,mid-1];
若key大于当前位置值arr[k],则在数列的后半段中继续查找arr[mid+1,high],
直到找到为止,时间复杂度:O(log(n))
对于区间[a,b] [a,b][a,b]上连续不断且f(a)⋅f(b)<0 f(a)·f(b)<0f(a)⋅f(b)<0的函数y=f(x) y=f(x)y=f(x),通过不断地把函数f(x) f(x)f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。
通俗语言就是将搜索空间不断的减半,从而逼近解的过程。
2三分法
在区间内用两个mid将区间分成三份,这样的查找算法称为三分查找,也就是三分法,三分法常用于求解单峰函数的最值。
还有一种理解,即在二分查找的基础上,在左区间或者右区间上再进行一次二分。
二分法适用于单调函数,而单峰函数用二分明显不太好了,对于有些单峰函数,可以求导后转化为单调函数,从而使用二分,然而很多情况求导是很麻烦的,这时就需要用到三分了。
1.先将区间三分,每个区间的长度为1/3(right-left)
mid1=left+(right-left)/3;
mid2=right-(right-left)/3;
2.比较mid1和mid2谁更靠近极值,如果mid1更靠近极值,右区间改为mid2,否则左区间改为mid1(后面的代码都是 以求最大值为例)
if(calc(mid1)<calc(mid2))
left=mid1;
else
right=mid2;
6.数论
这个太难了o(╥﹏╥)o
ACM的课程虽然结束了,但是我会继续在ACM这条路上走下去,一直寻找最优解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值