第3章 枚举!
第1节 坑爹的奥数
口3 * 6528 = 3口*8256,在两个口内填入相同的数字使其成立:
package ch3; public class Meiju1 { public static void main(String[] args) { for(int i=1;i<=9;i++) { if( (i*10+3)*6528 == (30+i)*8256){ System.out.println(i); } } } }
一个循环就可以得出答案,答案为4.这就是简单的枚举,枚举的基本思想是“有序地尝试每一种可能”。
第二题,口口口+口口口=口口口
分别填入1-9使等式成立。如果仍然枚举,要用九层循环,要执行10^9次判断。
第2节 炸弹人
小霸王上的炸弹人游戏,现在要在一个地图里放一个炸弹(爆炸方向是沿x轴和沿y轴两个方向,炸弹距离极大,但不能穿墙),请问炸弹放在哪里能炸到最多的敌人?
用一个二维数组来存储这个地图,然后枚举每一个可以放炸弹的位置.
代码看起来有点长,实际上重复的很多,
package ch3; import java.util.Scanner; public class Meiju2 { public static void main(String[] args) { char[][] a= new char[20][20];//地图 Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); //读入地图,n行m列 for(int i=0;i<n;i++) { a[i] = sc.next().toCharArray(); } int sum=0; int map=0; int p=0; int q=0; //遍历地图每一点 for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { //判断平地 if(a[i][j]=='.') { sum = 0; int x = i; int y = j; while(a[x][y]!='#') { if(a[x][y]=='G') sum++; x--; } x = i; y = j; while(a[x][y]!='#') { if(a[x][y]=='G') sum++; x++; } x = i; y = j; while(a[x][y]!='#') { if(a[x][y]=='G') sum++; y++; } x = i; y = j; while(a[x][y]!='#') { if(a[x][y]=='G') sum++; y--; } if(sum>map) { map = sum; p=i; q=j; } } } } System.out.println("炸弹放在"+p+", "+q+"消灭敌人最多,消灭敌人数目为"+map); } }
测试样例 13 13 ############# #GG.GGG#GGG.# ###.#G#G#G#G# #.......#..G# #G#.###.#G#G# #GG.GGG.#.GG# #G#.#G#.#.### ##G...G.....# #G#.#G###.#G# #...G#GGG.GG# #G#.#G#G#.#G# #GG.GGG#G.GG# ############# 测试结果 炸弹放在9, 9消灭敌人最多,消灭敌人数目为8
第3节 火柴棍等式
用一定数量(本题最多24根,除去+、=的4根最多还剩20根)的火柴棍摆出A+B=C的等式,
同样枚举可以完成,主要有两个注意点,一是枚举的范围,A、B、C的范围是0-11111,如果每位都是1的话,20根火柴可以是10个1。只考虑A,A的范围是0-十个1.再考虑C, C=A+B,所以C的位数大于等于A的位数,所以A的位数最多是5位。实际上,如果再考虑B的话,这个范围会更小。B至少占两根,那么剩下18根,A最大为1111
package ch3; public class Meiju3 { //返回x需要的火柴根数 public int fun(int x) { int num=0; int[] f = {6,2,5,5,4,5,6,3,7,6}; while(x/10!=0) { num +=f[x%10]; x/=10; } num+=f[x]; return num; } public static void main(String[] args) { Meiju3 m = new Meiju3(); int k = 18; //火柴棍数量 int sum = 0;//一共有sum组解 for(int a=0;a<=1111;a++) { for(int b=0;b<=1111;b++) { int c = a+b; if(m.fun(a)+m.fun(b)+m.fun(c)==k-4) { System.out.println(""+a+"+"+b+"="+c); sum++; } } } System.out.println("一共"+sum+"组解"); } }
第4节 数的全排列
给你3个数1,2,3,给出它们的所有排列可能,123,132,213,231,312,321是它们的全排列。
那么k个数的全排列呢(k是1-9)?可以用9层循环,加上if判断,但这样的话,只是if语句就要写8+7+6+5+4+3+2+1=36个判断。
一种比较简单的枚举是使用一个books[10]数组,标记数字1-9有没有使用过。
public static void main(String[] args) { int k=4; int[] books = new int[10]; for(int i=1;i<=k;i++) books[i]=1; for(int a=1;a<=4;a++) { books[a]=0; for(int b=1;b<=4;b++) { if(books[b]==0) continue; books[b]=0; for(int c=1;c<=4;c++) { if(books[c]==0)continue; books[c]=0; for(int d=1;d<=4;d++) { if(books[d]==0)continue; System.out.println(""+a+b+c+d); for(int i=1;i<=k;i++) books[i]=1; } } } } }