7/23学习心得+递归+二分

学习心得:

今晚题目做不出来,心态爆炸ing。一直超时,最讨厌优化了!!还有一个题看也看不懂,现在也不想思考了,呜呜呜,蓝瘦,好想看答案,还是抑制住了我的思想,啊,这种情况下果然脑子里面都是“你这么菜在这里丢什么人”之类的呢,心情沉重。毕竟他们仿佛都会但是我停止了思考~~就让我安静的做一条咸鱼(怎么可能啊喂!不过真的好渴望做一条咸鱼呢!)

看了题解之后:

那个一直超时的题,应该是先用函数找出所有的因数(而不是一个个遍历……呜呜),然后再判断因数是不是有重复数字就可以。

c题看起来很难,其实看懂了这个递归方程就很好理解了,因为只有一个递归的线路,所以只能循环一次,就到了递归的终止,而且从一个例子来看,经过一次递归,第一个数会到最后,其余的数字不变,所以要想结果是可以递增的,就是要把最大的放前面,然后其他的递增输出即可。

哎,心态爆炸ing,不想说话。不想做题。

今天本来想再交一交试试能不能过,结果编译错误……都能运行出答案你跟我讲编译错误??

今日份知识点总结:

1.前缀和

对于某个数列a,它的前缀和数列s是通过递推得到的信息之一,往往在开始做题的时候,就可以利用a[i]求出对应的s[i]。部分和,即数列a从l->r这一部分的和,可以表示为对应的s之差:sum[l,r]=s[r]-s[l-1]。

二维矩阵中,也是类似的推导过程。

a[i][j]=s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r](最后这一项是因为在减去前两项时,多剪了一次左上角的区域,得到的a[i][j]变小了。

2.递归

这个递归看的!遇上了跟没遇见过一样!

以原问题为起点,尝试把状态空间缩小到已知的“问题边界”的路线,再通过这条路线反向回溯的遍历方式就是递归。即,由问题找路线(可以发现答案的路线),直到定义域的边界处,再由这个路线原路返回,并带回答案。

考虑问题发现可以递归后,可以用以下步骤来写出递归方程:

1.尝试缩小状态空间(由大问题化解为小问题)。

2.求解这个小问题,由结果看缩小的成功与否。

3.由小问题返回到大问题,答案拓展。

例题:

(1)1~n之中随机选取任意个数字,输出所有可能的求解方案

答:缩小为数字1、2中选择,发现任意一个数字有两条路径:选与不选。从1到2,选1也选2、选1不选2、不选1选2、不选1不选2,这四种答案,问题边界:选完第二个数。所以由此可知,在1~n中,每一个数都可以有选与不选两个递归路线,边界,递归的次数(已选过的数字的个数)>n。

返回过程:从1->n,每个数字都是选与不选,每次的选择都会有不一样的路径,不一样的可能,到n就输出。

(2)1~n全排列输出

答:缩小为1、2、3全排列。for(1~3)中,第一次循环选1,标记1已经选过一次,第二次依旧是1~3的循环,在没有被标记的数字中选下一个数字,直到选完所有的数字。同理,扩大之后也是这样的选择路径方法。

边界条件:已经选了n个数字。

注意:

1.局部变量不能太多,防止栈溢出。

2.非局部变量所有递归共有,必须进行现场还原,否则影响各层递归的数据。

3.二分

二分基础应用:在单调函数、单调队列之中进行查找,三分还能进行求峰值的问题。

二分有整数域和实数域两种

(1)整数域

参考书的二分写法保证答案在闭区间[l,r]中,循环当l==r时结束,每次二分mid都会划分于左半部分或者右半部分。

①结果属于>=某个数值(x)中的最小值时(要么是x本身,要么没有x时取大于x的第一个数字),相当于找满足条件的这个区间的最左边部分,如此看来,mid>x的部分可以舍去(所求在最左边),r=mid-1。相反,若找<=x的最大值,则舍去左半边,l=mid+1。

②mid=(l+r)/2  永远取不到r,所以这个mid用于舍弃右边部分,求最小值。

mid=(l+1+r)/2  永远取不到l,舍弃左半部分,求最大值。

③终止条件:l==r。

(2)实数域

有小数,所以l==r不怎么可能成立。

所以while()条件要变换:l+1e-5

其余部分一样。

3.3二分的现实应用

一个最优化问题也可以抽象为函数,不过这一次的解,由我们自己设定边界,求得满足条件且在边界周围的最优化解。

假设最优评分是mid,那么对于>mid的,现然不可能达到该评分,对于

例子:

n本书排成一排,第i本书的厚度是ai,把他们分成连续的m组,使厚度之和最大的一组在所有分组情况中最小。

思考:

假设最优厚度是mid,那么每次都减去一本书的厚度,看看以这个大小为边界,可以分成几组,因为要求最小值,舍右。如果恰好分成<=m组了,则r=mid看看还能不能更小,不能分成m组的话,说明这个厚度界限太大,l=mid+1,要将厚度的最优变得大一点。

3.7三分

有唯一的极大值点,或唯一的极小值点。

f(x)在定义域[l,r]上取lmid、rmid。(lmid

(1)如果f(lmid)

则,无论rmid在那一边,lmid必须始终在左边,由此得知,极值点横坐标一定大于lmid,则l=limd。

(2)如果f(lmid)>f(rmid)

同理,无论lmid在左在右,rmid始终在右,极值点一定在左边,所以r=rmid。

 

 

 

 

 

 

 

 

你可能感兴趣的:(c++学习心得,前缀和,递归,二分)