枚举,基于已有的知识进行答案猜测的一种问题求解策略。
从可能的集合中一一列举各元素,根据已经知道的知识,给一个猜测的答案。
Ex.以找到比N小的最大素数为例
枚举算法
对问题可能解集的每一项根据问题给定的检验条件判定哪些是成立的,使条件成立的即是问题的解。
枚举过程
1, 判断猜测的答案是否正确。(例如,2是小于N的最大素数吗)
2, 进行新的猜测:注意要保证,(1)猜测的结果必须是前面的猜测中没有出现过的。(每次猜测的素数要比之前的要大)(2)猜测的过程中要尽早的排除错误答案。(除2之外,只有奇数才可能是素数。)
所以要考虑到三个关键问题。
1, 给出解空间,建立简洁的数学模型。
2, 减少搜索的空间。 利用知识缩小模型中各个变量的范围。
3, 采用合适的搜索顺序。
先附上之前问题的解法
例一 熄灯问题
问题描述
有一个由按钮组成的矩阵,其中每行有6个按钮,共5行,每个按钮上有一盏灯。当你按下一个按钮后,该按钮以及其周围上下左右四盏灯都会改变,亮-->暗或者暗-->亮。 要求对矩阵中的每盏灯设置一个初始状态,请你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭。
ji
如果穷举所有的状态,即为2^(56)种,肯定是不现实的。
*那么此时穷举的技巧是,如果存在某个局部,一旦这个局部的状态被确定,那么剩余其他部分的状态只能是确定的一种,或者不多的n种,那么就只需要枚举这个局部的状态就可以。
本题是有这样的“局部”的,当第一行的开关状态确定后,如果要熄灭第一行的所有灯,只能依靠第二行在第一行亮灯的对应位置下Press,故在第一行状态后,第二行的状态实际上已经确定好了;依次类推,第三行第四行…所有有一个思路是枚举第一行的所有的状态,然后判断第五行是否恰好都熄灭。以下是代码:
讨厌的青蛙
问题描述
有一种青蛙,会跳跃稻田,从而踩踏稻子。青蛙总是沿着一条直线跳跃稻田,并且每次跳跃的距离都相同。(可竖直也可倾斜)。来看看标准输入输出。
那么,我们枚举的是什么?肯定不能枚举所有可能出现的情况。
我们知道,两点确定一条直线,所以基本思路就是枚举第一个点和第二个点。
先直接粘贴代码,注释中有比较详细的思路。总结在之后。
思路值得我们继续巩固的点有:
1,通过思考得到“局部”枚举的方式。
2,对标准库里面函数的运用,sort, 包括binary_search的运用;当然,有很多时候我们对一些复杂的数据结构进行排序时,需要我们自己进行操作符重载。