八のクイーンズ
トピック:
- エイトクイーン問題は、古い、よく知られた問題であるアルゴリズムをバックトラックの典型的なケースです。問題は、マックス・ベテルが1848年に提示した国際チェスプレーヤーです:8つのクイーンズの国際チェス8×8のグリッド上に置かれ、それがお互いを攻撃することはできません、任意の二つの王妃が同じ行にすることはできません、です、同じ行または同じスラッシュと尋ねたどのように多くの振り子方式に。
分析:
簡単に言えば、問題は、ピア・スラッシュの要件と同じ列のチェス盤8×8グリッドは、重複した女王の質屋を持っているどのように多くの振り子方式を頼むことができないということです。
再帰的に実装され、再帰的ではないことを確認ファイルに、最初のフォルダに最初に行くところ、ちょうど文書の数以下のフォルダのようなファイルを見つけ、最初のフォルダは次のフォルダがあり、見下ろしておきます見つかった場合、あなたはあなたが見つけるまで、同じレベル内のファイルのフォルダを見つけ、フォルダに戻ります、各フォルダ内のforループです。
8つのクイーンの問題はそれほどボードボードコピーコピーコピー操作は、まずボードを初期化する、と考えることができるため、第一、第二クイーン衝突の最初の行の最初の女王は、第二の行に見出すことができません紛争の位置は、他のグリッドを配置する行を変更した場合の位置プットは、今度は、女王に委託しました。ライングリッドが女王を置くことができない場合は、女王は、問題の前に入れて説明し、あなたはすべての振り子の方法を見つけるまで、女王は、位置、およびその論理を再考、女王を削除します。
八は、再帰的なコアコードをQUEENS:
public static void eightQueen(int row,int[][] board){
if(row==8){
count++;
System.out.println("第"+count+"种可能");
print(board); //打印棋盘
System.out.println();
}else{
int[][] newBoard=copyOf(board); //拷贝一个蓝本
for(int col=0;col<8;col++){
if(isNoDanger(row,col,newBoard)){ //该位置不冲突时
for(int c=0;c<8;c++){ //清行代码
newBoard[row][c]=0;
}
newBoard[row][col]=1; //放皇后
eightQueen(row+1,newBoard); //递归
}
}
}
}
コアコード解析は:
最初に来る、行= 0、最初の行があれば、パラメータは行8に渡されないように、結果はそれをしない示し、クイーンに配置することを意味し、その後、forループ、青写真コピー内部に進みます配置操作、ゼロからCOL、即ち、第1列の女王。他の女王が干渉しないようにするので、この時点で、最初の列の最初の行は、女王を取っておくために、確かに望ましいです。
クイーンはないコンフリクト(isNoDanger法)、順番に呼び出し独自の(すなわち、再帰的)、行プラス1であれば配置されている場合、振り子の女王の2行目を表します。サイクルのために行くために2行目の女王、2例、
-
最初のケース:サイクルのためにダウンした後、(つまり、再帰的にダウン)自分自身を呼び出して、isNoDanger法であって実行、行プラス1(すなわち、女王への3行目を入れていませんそのようなプッシュ)。
-
第二の場合:サイクルが終わりに来ていないisNoDanger法により、第二のラインは単に女王を置くことができない示すことができないトリガー再帰、Jiubuyongtiバック、女王のための最初の行の位置を制御するために、この時間プラスCOL 1サイクル、すなわち、最初の行はそれ以上に行く前に、上記の論理を繰り返し、クイーンセルを戻します。
注:だけでなく、ラインをクリアするためのコードを追加してください、それはアクションが(回避干渉にダーティデータ)を0にクリアを実行する時期クイーンズに置きます
このコアコードの原理を理解し、8つのクイーンの問題が8つのクイーンの問題を、92例の合計を解決し、以下はJavaで実装完全なコードです。
public class EightQueen {
static int count=0; //有多少只可能
public static void main(String[] args) {
int[][] board=new int[8][8];
eightQueen(0,board);
}
//递归函数
public static void eightQueen(int row,int[][] board){
if(row==8){
count++;
System.out.println("第"+count+"种可能");
print(board); //打印棋盘
System.out.println();
}else{
int[][] newBoard=copyOf(board); //拷贝一个蓝本
for(int col=0;col<8;col++){
if(isNoDanger(row,col,newBoard)){ //该位置不冲突时
for(int c=0;c<8;c++){
newBoard[row][c]=0;
}
newBoard[row][col]=1; //放皇后
eightQueen(row+1,newBoard); //递归
}
}
}
}
//判断该位置是否与其他皇后冲突
private static boolean isNoDanger(int row, int col, int[][] newBoard) {
//向上
for(int r=row-1;r>=0;r--){
if(newBoard[r][col]==1){
return false;
}
}
//向左上
for(int r=row-1,c=col-1;r>=0&&c>=0;r--,c--){
if(newBoard[r][c]==1){
return false;
}
}
//向右上
for(int r=row-1,c=col+1;r>=0&&c<8;r--,c++){
if(newBoard[r][c]==1){
return false;
}
}
return true;
}
//复制棋盘
private static int[][] copyOf(int[][] board) {
int[][] newBoard=new int[board.length][board.length];
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
newBoard[i][j]=board[i][j];
}
}
return newBoard;
}
//打印棋盘
private static void print(int[][] board) {
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}
}
焦点は、コードのコア部分、再帰の考え方、すなわち、はっきりと多くを行うような再帰的な質問のクラスを理解するための再帰的な考え方です。