1. 程式人生 > >演算法之6-回溯法解數獨問題

演算法之6-回溯法解數獨問題

 剛開始學習的時候,總是不知道對陣列進行回溯的時候,怎麼保證找到的是下一個空值, 所以寫好一半的程式碼就放在一邊,一個星期之後回過頭再看回溯法解數獨的時候,突然醒悟過來:

原來在構造陣列的時候,以0值代替空值,當從1-9的某一個數填入該處的時候,該處就不是0值,回溯重新呼叫方法的時候,找到的0值就是下一處的0值了.
注意點:  
 (1).sudoku方法的返回值是布林值,這樣子"&&"兩邊才都是布林值
 (2)九宮格的獲得iGrid和jGrid都是用i,j對3整除再乘以3(以前錯誤認識:九宮格是以i,j為中心的九宮)
 (3)數獨的表示,空值用0表示
今天還有其它事,把待解決的記錄下來,以便以後參考:
  待解決問題:
   (1)輸出多個相同的數獨解
程式碼如下:
public class Sudodu {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[][] chess = { 
				{0,4,2,0,6,3,0,0,9},
				{6,0,0,0,1,0,0,0,5},
				{3,0,0,0,2,0,4,8,0},
				{1,0,0,5,0,2,6,0,8},
				{4,0,0,0,0,7,0,0,1},
				{9,0,5,6,0,0,0,0,7},
				{0,3,6,0,5,0,0,0,2},
				{2,0,0,0,7,0,0,0,4},
				{7,0,0,2,9,0,8,5,0}
				} ;
		sudoku(chess);
}

static boolean sudoku(int[][] chess) {
		// TODO Auto-generated method stub
		for(int i=0;i<9;i++)
		{
			for(int j=0;j<9;j++)
			{
				       //過濾掉不為0的情況
				   if(chess[i][j] != 0)
				  	continue;
						for(int d=1;d<=9;d++)
						{
							chess[i][j]=d;
							if(isValid(chess,i,j) && sudoku(chess) )
							{
								shuchushudu(chess);
								return true;
							}
							chess[i][j]=0;
						}
						return false;
			}
		}
		return true;
	}

	private static void shuchushudu(int[][] chess) {
	// TODO Auto-generated method stub
		for(int i=0;i<9;i++){
			for(int j=0;j<9;j++)
			{
			System.out.print(chess[i][j]+"  ");
			}
			System.out.println(" ");
		}
	System.out.println("--------------");
}

	private static boolean isValid(int[][] chess, int i, int j) {
		// TODO Auto-generated method stub
		boolean flag=true;
		int data=chess[i][j];
		for(int k=0;k<9;k++)
		{
			//i行相等
			if( (k!=j) && (chess[i][k]==data))
			{
			  return false;
			}
			//j列相等
			if( (k!=i) && (chess[k][j]==data))
			{
				return false;
			}
		}
		//九宮相等
		int iGrid=(i/3)*3;
		int jGrid=(j/3)*3;
		for(int k2=iGrid;k2<iGrid+3;k2++)
		{
			for(int k3=jGrid;k3<jGrid+3;k3++)
			{
				if((i==k2) && (j==k3))
				{
					continue;
				}
				if(chess[k2][k3]==data)
				{
					return false;
				}
			}
		}
		return true;
	}
}
結果輸出:

5  4  2  8  6  3  7  1  9   
6  8  7  4  1  9  2  3  5   
3  9  1  7  2  5  4  8  6   
1  7  3  5  4  2  6  9  8   
4  6  8  9  3  7  5  2  1   
9  2  5  6  8  1  3  4  7   
8  3  6  1  5  4  9  7  2   
2  5  9  3  7  8  1  6  4   
7  1  4  2  9  6  8  5  3