什么是枚举
枚举算法是一种经典的暴力算法,是通过遍历所有候选答案以找到正确的解的问题解决策略;
枚举的基本框架
1.给出解空间
建立数学模型,确立候选答案的范围,从数学的角度说:就是给出可能解的集合,这是最关键的一步,确立正确的解空间是应用枚举算法的前提。
2.找到枚举的具体方法
在确立了正确的解空间后,还要知道怎么枚举才能找到正确的答案。
对于不同的问题,枚举的具体方法很可能是不同的。
枚举的种类
1.循环枚举
通过数层循环来达到穷举解空间里的解,找到正确的答案,是最基本的枚举算法
例:
求小于 N 的最大素数
纯暴力:
int n,i,j;
scanf("%d",&n);
for(i=n-1;i>=2;i--)
{
for(j=2;j<=i-1;j++)
if(i%j==0) break;
if(j==i) {printf("%d",i);break;}
}
优化版
int n,i,j;
scanf("%d",&n);
for(i=n-1;i>=2;i--)
{
for(j=2;j*j<=i;j++)
if(i%j==0) break;
if(j*j>i) {printf("%d",i);break;}
}
2.子集枚举
解决可化归为集合的子集问题的题目;
原理分析:
当题目中出现的数据体现出子集的性质后,我们将子集中的中出现的元素用1代替,补集中的元素用0代替;
举个栗子:给定一个集合A{1,2,3,4,5},其中子集A1{1,3,4,5},A2{1,4,5},A3{3},A4{2,3}就可以这样表示
56
∗(1)其实集合是有无序性的,但是按顺序来“编码”,不会破坏一般性;
∗(2)这里的“编码”规则是,二进制第n位与array[n]对应,尽管顺序相反程序也会“不重复”,“不遗漏”遍历解答树,但是会破坏二进制原有的顺序。
A中元素 |
1∗(1) |
2 |
3 |
4 |
5 |
二进制∗(2) |
十进制 |
在A1中的情况 |
1 |