这一篇文章主要说说一些基础算法,这些算是很多其他算法的基石。
主要包括 模拟,暴力,枚举,递归,贪心,分治。
1,模拟:
顾名思义,模拟就是。。。饿,模拟,有一些题目就是给你一些步骤,然后你写代码一步步去模拟那些步骤就行。这类题目主要属于基础题,但是当然如果需要模拟的步骤足够恶心的话,还是比较麻烦的。。。
具体模拟的例子在之后的练习中会遇到的,按照题目要求一步步做就行,一般算法难度比较小。
2,暴力:
顾名思义,暴力就是。。。饿,暴力。比如说题目让从平面上的10个点中取三个点,让他们形成的三角形面积最大。那么暴力的方法就是直接列举所有可能的组合情况,然后一个个的算,找到里面的最大值。。。就是这么暴力。
当然暴力不一定只是无脑的蛮力,有时可能需要根据题目去排除一些不可能的情况,让暴力更快。
当然采取暴力的话要看题目的数据范围,当然还要有胆子,一句话就是 人有多大胆,地有多大产。。。
3,枚举:
顾名思义,枚举就是。。。饿,枚举。就是一个个列举所有的数,然后一个个算就好了。和暴力感觉其实差不多。
比如说第二场那个H题,就需要一个比较聪明的枚举。枚举每一个起点显然会超时,所以需要各种转换,变成枚举长度,然后就可以证明只需要枚举 根号n 次就行。
所以说很多题目需要一些聪明的转化,然后再枚举。。。
4,递归:
顾名思义,递归就是。。。饿,递归。C++的书上面应该有说个函数的递归,没看到的先回去看看。
然后就是关于递归的经典的汉诺塔问题。
具体汉诺塔是什么请百度或者谷歌。
然后现在解决这个问题:一个 N 层的汉诺塔,输出他的移动步骤,从A杆到C杆。
解决的话就是我们先把一个 N-1 的汉诺塔从A移动到B,然后把最后一个从A移动到C,然后再把 N-1 的汉诺塔从B移动到C就行了。。。
N-1层的汉诺塔递归解决就行了。。。
具体代码如下:
void Hanoi(int N,char A,char B,char C) { if(N==1) { cout<<A<<" -> "<<C<<endl; return; } Hanoi(N-1,A,C,B); // N-1的,从A到B。 cout<<A<<" -> "<<C<<endl; Hanoi(N-1,B,A,C); // N-1的,从B到C。 }
建议好好看看最好理解这段代码。。。
递归差不多就是这样,借助函数的递归,把大的问题化成小的问题去解决,然后合并小的问题。。。
5,贪心:
顾名思义,贪心就是。。。饿,贪心。有一些问题让最后的结果最优,然后我们可以直接遍历,每次对于当前情况取最优的,无视会不会影响其他情况,然后只要能证明每次取当前最好的,总的结果是最好的,那么这样的贪心就是正确的。。。
比如说以下问题:
你带着一个容量为V的背包去市场,市场上面有N种节操在卖,其中第 i 种节操的单位体积的价格是 Pi,然后最多 Ci 体积的节操卖。
然后问最少花多少钱能把背包装满节操?
典型的贪心的题目,显然买最便宜的最好,所以每次找 Pi 最小的那个去买,如果全部买来还装不满背包,就买 Pi 第二小的。。。然后一直这样,一直到装满背包。。。
这样每次取最便宜的买,那么最后花的钱最少,这样正确性不用多说吧。。。
贪心差不多就是这样,但是注意有些问题可能看起来很对,但是可能偏偏贪心有漏洞,也有可能看起来就是不太对,但是其实可以证明某种贪心是对的。。。
6,分治:
顾名思义,分治就是。。。饿,分治。分而治之,这和递归差不多,其实分治一般就是通过递归来实现的。。。
把大的问题分成小的问题去解决,然后把这些小问题合并得到大的问题的解。具体的例子的话之后会说,都是很经典的算法。。。
具体的基础算法其实就这几个,他们都是很基本的东西,建议可以初步掌握先。然后很多很多的算法都是通过这些算法去搭建的。。。