蛮力法(brute force methord,也称穷举法或者枚举法)是一种简单直接地解决问题的方法,常常直接基于问题的描述。所以,蛮力法也是最容易应用的方法。
蛮力法所依赖的基本技术是遍历(traversal,也称扫描),即采用一定的策略依次处理待求解问题的所有元素,从而找出问题的解。依次处理所有元素是蛮力法的关键,为了避免陷入重复试探,应保证处理过的元素不再被处理。用蛮力法设计的算法,一般来说,都可以对算法的第一个版本进行一定程度的改进,提高其时间性能,但只能减少系数,而数量级不会改变。
由于蛮力法需要依次穷举待处理的元素,因此,用蛮力法设计的算法其时间性能往往也是最低的,典型的指数时间算法一般都是采用蛮力穷举。但是,基于以下原因,蛮力法也是一种重要的算法设计技术:
(1)理论上,蛮力法可以解决可计算领域的各种问题。对于一些非常基本的问题,例如,求一个序列中的最大元素,计算n个数的和等,蛮力法是一种常用的算法设计技术。
(2)蛮力法经常用来解决一些较小规模的问题。如果要解决问题的输入规模不大,用蛮力法设计的算法其时间是可以接受的,此时,设计一个更高效算法的代价是不值得的。
(3)对于一些重要的问题(例如排序、查找、串匹配),蛮力法可以设计一些合理的算法,这些算法具有实用价值,而且不受输入规模的限制。
(4)蛮力法可以作为某类问题时间性能的下界,来衡量同样问题的其他算法是否具有更高的效率。
应用实例——百元买百鸡问题
【问题】已知总金额为100元,公鸡5元一只,母鸡3元一只,小鸡1元三只,一共需要买100只鸡,求解公鸡、母鸡、小鸡各多少只?
【想法】设公鸡、母鸡和小鸡的个数分别为x、y和z,则有以下方程组成立:
则百元买百鸡问题转换为求方程组的解。应用蛮力法求方程组的解只能依赖试探变量x、y和z的值,验证x、y和z的某个特定值是否能够使方程组成立。
【算法】设公鸡、母鸡和小鸡的个数分别为x、y和z,注意到方程组可能有多个解,需要输出所有满足条件的解,设变量count表示解的个数,算法用伪代码描述如下:
输入:无
输出:公鸡、母鸡和小鸡的个数
1. 初始化解的个数count=0;
2. 循环变量x从0~20重复执行下述操作:
2.1 循环变量y从0~33重复执行下述操作:
2.1.1 z=100-x-y;
2.1.2 如果5x+3y+z/3=100,则count++;输出x、y和z的值;
2.1.3 y++;
2.2 x++;
3. 如果count=0,则输出无解信息;
【算法分析】算法由两层循环嵌套组成,基本语句为5x+3y+z/3=100,所以操作执行次数为21X34=714.
【算法实现】
C语言代码如下:
#include<stdio.h>
int main()
{
int x, y, z; //x、y和z表示 公鸡、母鸡和小鸡的个数
int count = 0; //解的个数初始化为0
for (x = 0; x < 20; x++) //公鸡个数的范围是0到20
{
for (y = 1; y <= 33; y++) //母鸡个数的范围是0到33
{
z = 100 - x - y; //满足条件x+y+z=100
if ((z % 3 == 0) && (5 * x + 3 * y + z / 3 == 100))
//满足条件总价为100元,且小鸡的个数应该是3的倍数
{
count++; //问题解的个数加一
printf("公鸡有%d只,母鸡有%d只,小鸡有%d只\n",x , y, z); //输出所有解
}
}
}
if (count == 0) //无解的情况
printf("问题无解");
}
输出结果:
//公鸡有0只,母鸡有25只,小鸡有75只
//公鸡有4只,母鸡有18只,小鸡有78只
//公鸡有8只,母鸡有11只,小鸡有81只
//公鸡有12只,母鸡有4只,小鸡有84只
参考书籍:《算法设计与分析》(第2版)