題目
/* 方格填數 如下的10個格子 +--+--+--+ | | | | +--+--+--+--+ | | | | | +--+--+--+--+ | | | | +--+--+--+ (如果顯示有問題,也可以參看【圖1.jpg】) 填入0~9的數字。要求:連續的兩個數字不能相鄰。 (左右、上下、對角都算相鄰) 一共有多少種可能的填數方案? 請填寫表示方案數目的整數。 注意:你提交的應該是一個整數,不要填寫任何多余的內容或說明性文字。*/
答案
1580

代碼
1 public class Main { 2 static int sum = 0 ; 3 public static void main(String[] args) { 4 int a[] = {0,1,2,3,4,5,6,7,8,9}; 5 int b[] = new int[10]; 6 String s = ""; 7 f(a,b,0,s); 8 System.out.println(sum); 9 } 10 private static void f(int[] a,int[] b,int k,String s) { 11 if(k!=0 && k!=1 && k!=4 && k!=8 ){ 12 if(Math.abs(b[k-1]-b[k-2])==1) return; 13 } 14 if(k>=4 && k<=10 && k!=7){ 15 if(Math.abs(b[k-1]-b[k-4])==1) return; 16 } 17 if(k>=5 && k<=10){ 18 if(Math.abs(b[k-1]-b[k-5])==1) return; 19 } 20 if(k==6 || k==7 || k==9 || k==10){ 21 if(Math.abs(b[k-1]-b[k-6])==1) return; 22 } 23 24 if(k==a.length) { 25 sum++; 26 System.out.println(s); 27 return; 28 } 29 for(int i=0;i<a.length;i++){ 30 String ss = s; 31 if(a[i]==-1) continue; 32 b[k] = a[i]; 33 ss += a[i]; 34 a[i] = -1; 35 f(a,b,k+1,ss); 36 a[i] = b[k]; 37 } 38 39 40 } 41 }
分析
這又是一道涉及到排列組合的算法題,我用的是比較簡單和常見的解法,利用循環遞歸,開始依次向方格里面填數, 每填一個數都會判斷一下這個數是不是符合條件,如果符合條件則遞歸進去填下一個,如果不符合條件則return,當滿足在滿足條件的情況下數填完之后(k==10),則sum++,計數加一
因為判斷條件對方格有所依賴,所以想在短時間內寫出一個比較完美通用的算法是有點困難的,我們可以把情況細分,使得條件結構更清晰一點,
再說一個我覺得比較有創意的一點,這也是我最近學到的,就是用一個字符串,讓這個字符串也參與遞歸,就可以巧妙的可以把每次的情況都輸出來了,我很喜歡。
private static void f(int[] a,int[] b,int k,String s) { 11 if(k!=0 && k!=1 && k!=4 && k!=8 ){ 12 if(Math.abs(b[k-1]-b[k-2])==1) return; 13 } 14 if(k>=4 && k<=10 && k!=7){ 15 if(Math.abs(b[k-1]-b[k-4])==1) return; 16 } 17 if(k>=5 && k<=10){ 18 if(Math.abs(b[k-1]-b[k-5])==1) return; 19 } 20 if(k==6 || k==7 || k==9 || k==10){ 21 if(Math.abs(b[k-1]-b[k-6])==1) return; 22 } 23 24 if(k==a.length) { 25 sum++; 26 System.out.println(s); 27 return; 28 } 29 for(int i=0;i<a.length;i++){ 30 String ss = s; 31 if(a[i]==-1) continue; 32 b[k] = a[i]; 33 ss += a[i]; 34 a[i] = -1; 35 f(a,b,k+1,ss); 36 a[i] = b[k]; 37 } 38 39 40 }