看这个算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每个五角星代表 1 ~ 9 的不同的数字。
这个算式有多少种可能的正确填写方法?
173 + 286 = 459
295 + 173 = 468
173 + 295 = 468
183 + 492 = 675
以上都是正确的填写法!
注意:
111 + 222 = 333 是错误的填写法!
因为每个数字必须是不同的!
也就是说:1~9中的所有数字,每个必须出现且仅出现一次!
注意:
不包括数字“0”!
注意:
满足加法交换率的式子算两种不同的答案。
所以答案肯定是个偶数!
首先我们看一下简单的暴力破解方法:
暴力破解方法很简单,9层循环,判断是否同时满足 a+b=c 和 1~9仅出现一次 这两个条件,然后输出。
大致的思路很简单,但是其中需要处理很多细节,比如循环条件的控制。
代码中 f() 方法是用来判断是否满足 1~9仅出现一次 这个条件的返回类型为boolean的方法。思路为,把数据存入一个数组 x[] ,使用冒泡排序进行排序,再每位比较是否为1~9十个数字,相同则说明数组中1~9仅出现一次,return true 完成判断。
import java.util.Vector;
public class Main1 {
public static int count;
public static boolean f(int a,int b,int c,int d,int e,int f,int g,int h,int l){
int[] x = new int[9];
x[0] = a;x[1] = b;x[2] = c;
x[3] = d;x[4] = e;x[5] = f;
x[6] = g;x[7] = h;x[8] = l;
//冒泡排序
for(int i=0;i<9;i++){<span style="white-space:pre"> </span>//大循环
for(int j=0;j<8-i;j++){<span style="white-space:pre"> </span>//一轮比较后,最后一位一定是最大的。下次比较去掉最后一位。这就是-i的来源
if(x[j] > x[j+1]){
int temp = x[j];
x[j] = x[j+1];
x[j+1] = temp;
}
}
}//排序完毕
int n=0;
for(int k=0;k<9;k++){
if(x[k] == k+1)
n++;
}
if(n==9) return true;
else return false;
}
public static void main (String[] args) {
//暴力破解
for(int a=1;a<10;a++)
for(int b=1;b<10;b++)
for(int c=1;c<10;c++)
for(int d=1;d<10;d++)
for(int e=1;e<10;e++)
for(int f=1;f<10;f++)
for(int g=1;g<10;g++)
for(int h=1;h<10;h++)
for(int i=1;i<10;i++){
if( (a*100+b*10+c + d*100+e*10+f == g*100+h*10+i) && f(a,b,c,d,e,f,g,h,i) ){
System.out.println(" "+a+b+c+" + "+d+e+f+" = "+g+h+i);
count++;
}
}
System.out.println(count);
}
}
第二种解法用到了Vector类,以前没有接触过这个类,通过查阅API文档,记录学习一下。
Vector
类可以实现可增长的对象数组。Vector(Collection<? extendsE> c)
构造一个包含指定 collection 中的元素的向量,这些元素按其 collection 的迭代器返回元素的顺序排列。
Character 类在对象中包装一个基本类型 char
的值。Character
类型的对象包含类型为char
的单个字段。
import java.util.Vector;
public class Main1 {
public static int count;//不想让count成为递归方法的形参可以将它定义为静态变量,初始值为0
public static void f(Vector<Character> source,Vector<Character> result){
if(source.size()==0){
int a=(result.elementAt(0)-'0')*100+(result.elementAt(1)-'0')*10+result.elementAt(2)-'0';
int b=(result.elementAt(3)-'0')*100+(result.elementAt(4)-'0')*10+result.elementAt(5)-'0';
int c=(result.elementAt(6)-'0')*100+(result.elementAt(7)-'0')*10+result.elementAt(8)-'0';
if(a+b==c){
System.out.println(a+" + "+b+" = "+c);
count++;
}
}
else{
//这个递归的核心思想还是枚举,一个循环列出所有Vector source和result的可能
for(int i=0; i<source.size(); i++){
result.add(source.elementAt(i));
sourse.remove(i);
f(sourse,result);
//回溯
source.add( i,result.elementAt( result.size() - 1 ) );
result.remove( result.size() - 1 );
}
}
}
public static void main (String[] args) {
Vector<Character> sourse = new Vector<Character>();//源
Vector<Character> recult = new Vector<Character>();//结果
for(int i=1;i<=9;i++){//注意此处的循环条件,从1到9,赋给Vector类型的变量source
source.add( (char)(i+'0') );//转换成AscII码
}
f(source,result);
System.out.println(count);
}
}