暴力枚举法,也叫做穷举法,条件范围不大的时候就可以用枚举法
看下面这个问题:
鸡兔问题
鸡兔同笼,头则50,脚则120。
问:鸡兔各几何。
public class BruteForce01 {
public static void main(String[] args) {
int HEAD=50;//设置头数
int FOOT=120;//设置脚数
for (int x = 0; x <HEAD ; x++) {//利用头数来循环,x为鸡,y为兔
int y=50-x;//兔子数就等于总数-鸡数
if(x*2+y*4==FOOT){//用脚数来当判断条件
System.out.println("鸡x="+x+"\t"+"兔y="+y);
}
}
}
输出结果:鸡x=40 兔y=10
上面是一个最简单的可以用暴力枚举法解决的问题
下面这个问题也同理可以用暴力枚举法解决
韩信点兵
今有士卒,千余人许。
5人为伍,则余1
7人为伍,则余2
8人为伍,则余3
试求确数
public class BruteForce02 {
public static void main(String[] args) {
for (int i = 1000; i <2000 ; i++) {//千余人,最多不超过20人
if (i%5==1 && i%7==2 && i%8==3){//将题目条件写进判断
System.out.println(i);
}
}
}
}
输出结果 :
1171
1451
1731
这个方法仅仅是对所有可能的情况逐一的列举,并且用条件进行筛选,然后把满足条件的最终列出来。
这个方法虽然很简单有效,但当要考虑很多情况的时候,计算机的运行就会很吃力,
所以我们可以在逻辑上去排除一些不可能出现的情况,减少计算机的压力。
而剪枝,就是尽量的让计算机去避免无用的徒劳的操作。
来看下面这个问题
要找8元钱
有零钞:5元,2元,1元,5角
求所有找零方案
由于java中浮点数会有误差,所以用1角作单位,便于计算
即8元=80角,5元=50角,2元=20角,1元=10角
下面是暴力枚举法解决
public class EnumerationPrune01 {
public static void main(String[] args) {
for (int a = 0; a <=80/50 ; a++) {
for (int b = 0; b <=80/20 ; b++) {
for (int c = 0; c <=80/10 ; c++) {
for (int d = 0; d <=80/5 ; d++){
if(a*50+b*20+c*10+d*5==80){
System.out.println(a+","+b+","+c+","+d);
}
}
}
}
}
}
}
显然,用了四个循环嵌套,暴力的解决了问题
然而,如果数值很大的话,这个运算就会很慢,所以我们可以用“剪枝”这个方法
剪枝的思想就是剪掉不可能出现的情况,避免计算机多余的运算
public class EnumerationPrune01 {
public static void main(String[] args) {
for (int a = 0; a<=80/50 ; a++) {
for (int b = 0; b <=80/20 ; b++) {
if((80-a*50-b*20)<0) break; //剪枝,如果80被50和20分完了,那么就不用再运算下去了
for (int c = 0; c <=80/10 ; c++) {
if((80-(a*50+b*20+c*10))<0)break;//同上理
int d= (80-(a*50+b*20+c*10))/5;//用这种方式来表示d,可以减少一个循环
if(a*50+b*20+c*10+d*5==80){
System.out.println(a+","+b+","+c+","+d);
}
}
}
}
}
}
两种方法输出的结果都是一样的!
再看下面一题:
三位数的平方的尾数还是自己
public class EnumerationPrune02 {
public static void main(String[] args) {
for (int i =100 ; i <1000 ; i++) {//100-1000三位数之间循环
int n=i*i;//用n来表示i的平方
int m=i%10;//用m来表示i的个位数
if(m!=0&&m!=1&&m!=5&&m!=6){//这里是剪枝:如果m,也就是i的个位数不等于0并且不等于1并且不等于5并且不等于6,那么这个数一定不符合题意!跳过
continue;
}
if(n%1000==i){//判断平方后的尾数是否等于自己
System.out.println(i+","+n);
}
}
}
}
输出结果:
376,141376
625,390625
总结:剪枝就是要把不符合逻辑要求的情况排除!