Backtracking Method and Its Application--The Problem of Eight Queens

https://www.cnblogs.com/bigmoyan/p/4521683.html
https://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html
https://blog.csdn.net/qq_32400847/article/details/51474105#commentBox

1. Backtracking

The backtracking method is a kind of optimal search method, which searches forward according to the optimal conditions to achieve the goal. When a certain step is explored, it is found that the original choice is not good or the goal is not achieved, so he will step back and choose again.
This technique of going back and going back if it fails is the backtracking method , and the point of a certain state that satisfies the backtracking condition is called the " backtracking point ".

The so-called retrospective method, the name is tall, the thinking is very simple. Imagine putting you in a maze and wanting to get out of the maze. What is the most direct way? Yes, try. First choose a path to go, then go back and try another path if you can't get it, and continue backing until you find an exit or you can't get out of all the roads.

2. The Eight Queens Problem

It is an old and well-known problem and a typical case of backtracking algorithms.
The problem was raised by the chess player Max Bethel in 1848: Place eight queens on an 8×8 chess board so that they cannot attack each other, that is, no two queens can be in the same row. On the same column or on the same diagonal line, ask how many ways there are.

Guessed, there are 92 correct answers.

For details, please refer to this article:
https://www.cnblogs.com/bigmoyan/p/4521683.html The
bloggers are well-written with pictures and texts , easy to understand, witty and humorous, so good!

Just upload the code. Here I have enriched the blogger's code: not only printing the number of schemes, but also outputting the placement patterns in two ways.

  • One is the direct printing scheme;
  • The other is to organize the solution into a list for output (there is such a requirement in the programming questions of the LeetCode category). Leetcode51 question-N queen question

Java code

import java.util.ArrayList;
import java.util.List;

public class 八皇后问题方法二 {

	//记录方案数
	private int count = 0;
	
	//记录每一行皇后的位置
	private int[] queen = new int[8];
	
	//记录方案的列表
	private List<List<String>> results = new ArrayList<>();
	
	/**
	 * 主要的回溯函数
	 * @param row
	 */
	public void queen(int row){
		if(row == 8){
			//统计方案数
			count++;
			//打印方案
			showAnswer();
			//将结果统计成列表形式
			generateAnswer();
		}else{
			for(int j = 0;j<8;j++){
				queen[row] = j;
				if(isOk(row))
					queen(row+1);
			}
		}
	}
	
	/**
	 * 将结果组织成列表的形式
	 */
	private void generateAnswer(){
		List<String> ans = new ArrayList<>();
		for(int i = 0;i<8;i++){
			StringBuilder sb = new StringBuilder();
			for(int j = 0;j<8;j++){
				if(queen[i] == j){
					sb.append("Q");
				}else{
					sb.append(".");
				}
			}
			ans.add(sb.toString());
		}
		results.add(ans);
	}
	
	/**
	 * 打印合法的结果
	 */
	private void showAnswer() {
		System.out.println("答案是:");
		for(int i = 0;i<8;i++){
			for(int j = 0;j<8;j++){
				if(queen[i] == j){
					System.out.print("Q");
				}else{
					System.out.print(".");
				}
			}
			System.out.println();
		}
		
	}

	/**
	 * 判断是否能放置皇后
	 * @param row
	 * @return
	 */
	private boolean isOk(int row) {
		//依次判断前面的行中与当前行放置的皇后是否冲突
		for(int j = 0;j!=row;j++){
		//在同一列、在副对角线(右上到左下)、在主对角线(左上到右下),都是冲突的
			if(queen[row]==queen[j] || row+queen[row] == j+queen[j]|| row-queen[row] == j-queen[j]){
				return false;
			}
		}
		
		return true;
	}

	public static void main(String[] args) {
		八皇后问题方法二 qu = new 八皇后问题方法二();
		qu.queen(0);//进行计算
		System.out.println(qu.count);//打印方案数
		System.out.println(qu.results);//以列表的形式打印方案

	}

}


In addition, you may notice that the class name in the above code is method two . Yes, there is another way of writing.
However, personal feelings are not as easy to understand as above.

Let’s take a look at it. Thoughts are all the same retrospective method. The difference is the judgment of legal placement.

The above method uses an isOk function, and the
following one uses two arrays to store whether the main diagonal and the secondary diagonal have queens. Regarding this explanation, refer to the following article, it should be understandable.

Reference article:
https://blog.csdn.net/qq_32400847/article/details/51474105#commentBox

The code refers to Baidu Encyclopedia: The Eight Queens Problem

Java code


public class 八皇后问题 {

	private int[] column; //同栏是否有皇后,1表示有
    private int[] rup; //右上至左下是否有皇后
    private int[] lup; //左上至右下是否有皇后
    private int[] queen; //解答
    private int num; //解答编号
    
    
    public 八皇后问题(){
    	column = new int[8+1];
        rup = new int[(2*8)+1];
        lup = new int[(2*8)+1];
        for (int i = 1; i <= 8; i++)
            column[i] = 0;
        for (int i = 1; i <= (2*8); i++)
            rup[i] = lup[i] = 0;  //初始定义全部无皇后
        queen = new int[8+1];
    }
    
    public void backtrack(int i) {
        if (i > 8) {
            showAnswer();
        } else {
            for (int j = 1; j <= 8; j++) {
                if ((column[j] == 0) && (rup[i+j] == 0) && (lup[i-j+8] == 0)) {
                    //若无皇后
                    queen[i] = j; //设定为占用
                    column[j] = rup[i+j] = lup[i-j+8] = 1;
                    backtrack(i+1);  //循环调用
                    column[j] = rup[i+j] = lup[i-j+8] = 0;
                }
            }
        }
    }
 
    protected void showAnswer() {
        num++;
        System.out.println("\n解答" + num);
        for (int y = 1; y <= 8; y++) {
            for (int x = 1; x <= 8; x++) {
                if(queen[y]==x) {
                    System.out.print("Q");
                } else {
                    System.out.print(".");
                }
            }
            System.out.println();
        }
    }
    
	
	public static void main(String[] args) {
		八皇后问题 queen = new 八皇后问题();
        queen.backtrack(1);
	}

}

Guess you like

Origin blog.csdn.net/fxjzzyo/article/details/89107131