看這個算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每個五角星代表 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);
}
}