课程总结

课程学习

(一) 递归算法
程序直接或间接调用自身的编程技巧称为递归算法,它通常将一个大的复杂的问题层层转化为与原问题相似的较小问题求解。递归算法解体通常有三个步骤:

  1. 分析问题寻找大规模问题与小规模问题的关系
  2. 设置边界、控制递归
  3. 设置函数、确定参数
    递归模板首先判断是否到达边界条件,在对现在的条件具体处理与分析,然后进行更深层的递归。
    (二) 贪心算法
    贪心算法求局部问题的最优解,他不是从整体方面考虑问题,而是将一个问题分成若干个子问题,找到子问题的最优解然后回溯解决问题。利用贪心算法,解题需要考虑两个问题。
    (1) 该题是否适于用贪心算法求解。
    (2) 如何选择贪心标准,使得这个问题有最优解。
    贪心算法的经典问题,例如背包问题和区间调度问题。处理背包问题时,有两种情况一种是物品不可分割,另一种是物品可以分割背包会被装满的,另一种是物品不可分割背包不一定能够装满,前者可以使用贪心算法,根据优先级排序,依次装入即可,后者需要使用动态规划。区间调动问题需要根据活动时间是否排斥来根据起始时间或结束时间进行排序,然后在每一个区间选取端点判断。
    (三) 线性动态规划
    动态规划是分阶段求最优解的算法首先将复杂问题按阶段划分成子问题再枚举子问题的各种可能,从中找出最优解最后利用子问题的最优解求出原问题的最优解,动态规划模型要找准上一模型与这一模型的联系,然后选择不同的决策接近原问题的最优解,然后每个状态都这样累次叠加求出原问题的最优解。动态规划的一般解法是递归。如吃金币游戏,在(a,b)点吃金币的最大值为从左边的方格与上边的方格金币数的较大者加上该点的金币数。

比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).你的任务,就是对于给定的序列,求出最长上升子序列的长度。最长上升子序列问题,则是固定一个索引值,在他的前面的索引值中寻找一个符合条件的最长序列,累加起来便是答案。

(四)背包问题
1.01背包

01背包在把第i件物品装入j容量时有两种情况——装与不装,分别与上次的最优值相加再取最优值
for(int i=1;i<=n;i++)
for(int j=w[i];j<=N;j++)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+w[i]);

因为上一个序列在用过后在计算中不再起作用可以将它化为滚动数组
for(int i=v;i<=w[i];i++)//更新循序从大到小
dp[j]=max(dp[j],dp[j-w[i]]);
2.完全背包
感觉完全背包是在01背包上剔除不放的情况增加讨论每一种物品的个数
但是注意完全背包在每一区间放的物品大小等于区间大小
所以初始化时除了dp[0][0]外其余的都赋予-INF
for(int i=1;i<=n;i++)
for(int j=w[i];j<=N;j++)
for(int k=0;k<=N/w[i];k++)
dp[i][j]=max(dp[i-1][j-kw[i]]+kw[i],dp[i][j]);
->max(dp[i-1]j,dp[i-1][j-kw[i]]+kw[i]](k>1));
->max(dp[i-1]j,dp[i-1][j-kw[i]-w[i]]+kw[i]+wi);
dp[i][j-w[i]]->max(dp[i-1][j-kw[i]-w[i]]+kw[i]+w[i]);
->max(dp[i-1]j,dp[i-1][j-w[i]]+w[i]);
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]);
可得一维数组dp[j]=max(dp[j],dp[j-w[i]]+w[i]);//从前往后写入

3.多重背包

二进制优化任意一个整数都可以看做为20+21+……+2^n+(m)
可以将背包的容量拆分为上面的几个数的不同情况组合相加
POJ1014-Dividing
有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份,是两份的总价值相等,其中一个物品不能切开,只能分给其中的某一方
题意:是否可以在任意数量的6种物品中找几个物品使到他们价值和为总价值和的一半(物品不可分割)
void complete_pack(int a,int c,int w){
for(int i=c;i<=v;i++)
a[i]=max(a[i],a[i-c]+w);//完全背包是根据已更新的数据更新
}
void zerone_pack(int a,int c,int w){
for(int i=v;i>=c;i–)
a[i]=max(a[i],a[i-c]+w);//01背包是根据未更新的数据(i-1)更新
}
void multi_pack(int a,int c,int w,int m){
if(c
m>=v){
complete_pack(a,c,w);
return ;
}
int k=1;
while(k<m)
{
zerone_pack(a,k
c,k
w);
m-=k;
k*=2;
}
zerone_pack(a,mc,mw);
}
(五)二分法及三分法
二分查找三分查找都是在有序数列中,将整个集合分为两部分,然后以此类推直到找到合适的值或者近似值。
二分查找模板
设judge(m)随着m增大而增大
基本查法
while(l<=r)
{
int mid=(l+r)>>1;
if(judge(mid)==VALUE)
return mid;
else if(judge(mid)>VALUE)
r=mid-1;
else l=mid+1;
}
左查法
while(l<r)
{
int mid=(l+r)>>1;
if(judge(mid)<=VALUE)
l=mid+1;
else
r=mid;
}
右查法
while(l<r)
{
int mid=(l+r)>>1;
if(judge(mid)>=VAlUE)
r=mid;
else l=mid+1;
}
return r-1;
高精度二分法
while(r-l>1e6)
{
double mid=(l+r)/2;
if(judge(mid)<VALUE)
l=mid;
else r=mid;
}
二分法实在单调递增或递减数据基础上不断缩小范围(通过判断大于小于查询值)选取合适的数据,三分法是在一段有单个极值的数据上,缩小范围(通过极值的性质取较小或较大值),取到极值。
三分法

while(l+0.00001<r)//使精确到小数点后三位
{
double mid=(l+r)/2.0;
double midmid=(mid+r)/2.0;
if(calce(mid)>calce(midmid))
r=midmid;
else l=mid;
}
(六)数论
对素数研究的数学理论
快速幂
求素因子
求因子个数
最大公因数
最小公倍数
因数分解
扩展偶几米的
逆元
埃氏筛选
中国剩余定理
欧拉函数

(七)树状数组
索引值为奇数只储存自身索引值,为偶数管理索引值的二进制形式从后起到前端或到1为止0的数目个值。
(八)线性数组
本质是一颗二叉树,每个节点储存的是一段区间的和,与堆结构有很大的相似性。
(九)单调队列
队列元素之间的关系具有单调性,而且,队列的队首与队尾都可以进行出队操作,只有队尾可以进行入队操作。与之前学得单调栈不同的是它可以队首进行出队操作。

关于ACM的心得


ACM课程结束了。在报ACM之前我接触到的算法比较简单,而且那时候学的专业知识比较少,很好奇以后学的专业知识是什么,也时而遇到一些未接触到的算法,比较好奇。在第一次退课时,有很多人说ACM挂科率很高,但是那时候我比较自信于是抱着试试看的态度去报ACM,就算学的不好也总会获得一些知识,而且我听说ACM含金量高,我就报了,但随着我对ACM接触越来越深,我发现ACM与原来学的C++完全不同,他讲的是算法思想的构架与实现,而c++只是其中的一个语言工具,这给了我数学学科的感觉,所以我觉得学起来比较吃力。每次遇到老师布置的练习题,基本上都会遇到那种根本想不到的解法,感觉自己还是接触的太少。然后遇到这种不会的题我便跑去看题解,虽然大多数情况下能够看懂,但毕竟不是自己想出来的,没有系统的总结与认知,再次遇到类似的问题还是束手无策,再加上这个特殊的时期在家比较无聊,由于个人因素,所以心情比较烦躁,所以有点学不进去,所以我投入了较多的但是在家呆久了,也许是不习惯,我发现我失去了以前曾有的目标,开始变得迷茫了。我开始质问自己为什么学ACM甚至为什么计算机这一学科。我知道我自己也无法得出答案,所以我应该继续学下去。然后在不断做题中,ACM其实训练了我的思维,以往遇到题目,只是简单地利用某些简单的贪心做法然后暴力地解决问题,而现在我可以使用更多种的方法最优地解决问题,以前我对这些算法原理一无所知,但现在我可以比较熟悉的使用它们,在了解每一个算法原理后,我对ACM更加的了解了。在第二次退课时,虽然我有些迷茫但我还是坚持了ACM,因为通过它我的专业知识与技能能够得到较大提高,而且在ACM中有许多非常厉害的大佬,这让我增长了见识。

关于比赛心得

时间学习,但是我发现我的效率并不高,常常被难住,于是我便开始总结。第一次打CF是刚放寒假听说有个比赛,便开始打,但由于是外网显然比赛题目也是英语,所以比较激动但是我发现,这个题目不好阅读,一旦出现不会的单词就无法继续理解题目了。在那场比赛后我便频繁使用百度翻译,可能是由于惰性,我渐渐地发现我的大脑懒得理解翻译后的题目了,于是我尽量自己去读。一开始我是奔着分数去打的,由于CF提交Wrong会扣分所以我一般先检查好再去提交,如果没有把握则不会提交,有几次我卡在了A题,心态直接崩了,根本没有心情去看下面的题,于是草草地关闭了浏览器睡觉去了。但是我发现这样会是我损失很多的收获,我便有时跳过几个题目。随着场次的增加,后来我逐渐意识到这样做是不对的,做出做不出题并不重要,重要的是确定思路,拓展思维,熟悉算法。于是在比赛过后,我便将没有解出来的题目做一遍,整理笔记,总结思路。之后老师让我们打牛客比赛,打了一场感觉自己掌握得并不熟练,但我感觉自己获得了提升。虽然现在分数并不好,但是也要砥砺前行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值