枚举法,作为编程世界里一个非常基本的方法或者说技巧,它也可以叫穷举法、暴力法、遍历法,深入了解一些算法后,你会发现它在算法世界当中的用途非常的广泛。
概括地说这种方法非常的简单,我们抽象点来说,对于一个问题的解x,这个解满足限制条件f(x),枚举法给出解决问题的方案是一一列举x所有可能的情况,然后判断是否满足限制条件f(x),如果满足,则x是问题的解;反之,不是。
枚举法虽然简单,但是在解决实际问题中往往伴随着比较巧妙的优化与筛选,而且在枚举算啊中体现出的“找到x所有可能的情况”,在其他的一些算法(比如计算几何)也有着用武之地。因此所谓暴力法看似暴力无脑,其实里面还是有很多需要深思熟虑的地方。
我们来看一个例子:对于()()()+()()() = ()()(),9个空填写1~9这9个数字各一次,请问会有多少种符合的情况?
显然我们枚举每一个()可能的取值,即[1,9],需要设置9层循环,然后判断这9个数是否相等,随后验证等式成立,但是基于这个思路编程我们发现在判断9个数是否相同的时候太过麻烦了,有没有较为简便的编码方式呢?
其实类似我们在第一章介绍的桶排序的方式,我们用a[i]表示第i个()的数字,然后我们用book[a[i]]来标记数字a[i]是否出现过,如果∑book[a[i]] = 9 ,则表明9个数字分别出现了一次,是满足限制条件的。
简单的参考代码如下。
#include<cstdio> int main() { int a[10] , i , total = 0 , book[10] , sum; for(a[1] = 1;a[1]<=9;a[1]++) for(a[2]=1;a[2]<=9;a[2]++) for(a[3]=1;a[3]<=9;a[3]++) for(a[4]=1;a[4]<=9;a[4]++) for(a[5]=1;a[5]<=9;a[5]++) for(a[6]=1;a[6]<=9;a[6]++) for(a[7]=1;a[7]<=9;a[7]++) for(a[8]=1;a[8]<=9;a[8]++) for(a[9]=1;a[9]<=1;a[9]++) { for(i = 1;i <= 9;i++) book[i] = 0; for(i = 1;i <= 9;i++) book[a[i]] = 1; sum = 0; for(i =1 ;i <= 9;i++) sum+= book[a[i]]; if(sum==9 &&100*a[1] + 10*a[2] + a[3] + 100*a[4] + 10*a[5] + a[6] == 100*a[7] + 10*a[8] + a[9]) { total++; } } printf("total = %d",total/2); //由加法交换律我们不难理解这里应该除2的,对于结果进行符合题意的筛选计算往往是枚举的关键 }
时间: 2024-10-22 19:21:29