理解顺序:枚举法 --> 递归/回溯法 --> 剪枝 (算法思想通用所有语言,这里采用主要Java书写)
枚举法:
将问题的所有可能的答案一一列举,然后根据条件判断此答案是否合适,合适就保留,不合适就丢弃。
例:在一个陌生的国度,有5种不同的硬币单位:15、23、29、41和67(分)。寻找所有组成18元8分(即1808分)的可能组合。假定对于所有面值的硬币你都有足够的硬币。
解:这道题也是一道经典的用枚举法求解的题。首先15分的硬币从0(最少)到1808/15种(最多);同理23分硬币0 ~ 1808/23(做除法);29分硬币0 ~ 1808/29;41分硬币0 ~ 1808/41;67分硬币0 ~ 1808/67;这样15、23、29、41、67分硬币只需满足15 * i+23 * j+29 * k+41 * h+67 * s=1808就是符合条件的组合;其中i,j,k,h,s都是在对应的硬币的范围之内(最少到最多);
for(int i=0;i<=n/15;i++)//15分硬币
{
for(int j=0;j<=n/23;j++)//23分硬币
{
for(int k=0;k<=n/29;k++)//29分硬币
{
for(int h=0;h<=n/41;h++)//41分硬币
{
for(int s=0;s<=n/67;s++)//67分硬币
{
if(i*15+j*23+k*29+h*41+s*67==n) //判断
{
printf("15分硬币%d个,23分硬币%d个,29分硬币%d个,41分硬币%d个,67分硬币%d个\n",i,j,k,h,s);
}
}
}
}
}
}
缺陷:
用枚举法解题的最大的缺点是运算量比较大,解题效率不高,如果枚举范围太大(一般以不超过两百万次为限),在时间上就难以承受。但 [3] 枚举算法的思路简单,程序编写和调试方便,比赛时也容易想到,在竞赛中,时间是有限的,我们竞赛的最终目标就是求出问题解,因此,如果题目的规模不是很大,在规定的时间与空间限制内能够求出解,那么我们最好是采用枚举法,而不需太在意是否还有更快的算法,这样可以使你有更多的时间去解答其他难题。