N queens problem (recursive backtracking)

  Today I talked about the problem after N, and now I will review it.

  The problem after N is to place n queens that are not attacked by each other on an N*N chessboard. The queen here refers to the queen in chess. According to the rules of chess, the queen can attack the pawns with the same slash in the current row and current column. Simply put, the positions of n queens cannot be in the same row, column, and slash. Because I have been learning backtracking algorithms these days, it is very simple to think of backtracking. This problem is also one of the classic backtracking algorithm exercises.

  Let's think about the conditions contained in the problem. The obvious condition is that the chessboard is n*n, and it is very simple to think that n queens cannot be in the same column, that is, there will be one queen in each column. The following is the implicit condition, the same row and the same column can be easily solved, the same slash is not very easy to think. Later, it was found that the queens with the same slash are all queens whose position difference is equal to the column where the queen is located. That is, the position of the queen has a slope of 1. Translated into a code language, the absolute value of the difference in the queen's position is equal to the absolute value of the difference in the queen's column. I'll talk about this later. The conditions are all finished, let's talk about the main body of the algorithm.

  The main body of the algorithm is composed of recursion. The recursive parameter is the column of the currently considered queen. For the convenience of the following calculation, the number of queens and the array are passed in here. Why pass in an array? Because I thought of a two-dimensional array at first, this is also easy to think of, but later I found that the form of the solution is related to the subscript of the array, so I simply changed the two-dimensional array into a one-dimensional array, and changed the column where the queen is located. is the subscript of the array. This saves a lot of useless work. The recursive boundary is that the position of k is greater than or equal to n. The main body of the recursion is a for loop, which assigns the value of the loop to the current position of the array, and checks whether the current position is correct. When it comes to checking the position of k, let's talk about this method. It is very simple. It is to judge whether the current position meets the conditions of the problem, and there must be a return value to facilitate subsequent calls. The for loop is also used when testing.

  After the main body of the algorithm is finished, paste the code directly below. The code is as follows:

package sf;

import java.util.Scanner;

// Problem after N
public class demo7
{
	public static int num=0;//accumulation sum
	// Determine if the current position is correct
	public static Boolean judge(int[] p,int k)
	{
		for(int i=0;i<k;i++)
		{
			//The determination of the absolute value and the determination of the column. (no judgment line)
			if((Math.abs(i-k)==Math.abs(p[i]-p[k]))||(p[i]==p[k])) {
				return false;
			}	
		}
	  //Pay attention to the position of this return, here is to make the for loop loop all the time without being interrupted by the middle position, you can put
	  //This return is put into the for loop to experience it. It will be found that the number of solutions will increase.
	  return true;
	}
	//The main body of the algorithm recursively backtracks k as the current considered position
	public static void Queen(int[] p,int n,int k)
	{
		//The method body here still needs to think more
		if(k>=n)
		{
			num++;
			// print the result
			for(int i=0;i<n;i++)
				System.out.print(p[i]);
			System.out.println("");
		}else{
			for(int j=1;j<=n;j++)
			{
				//System.out.println(k);
				//Assign the position of the queen to the elements in the array, which is equivalent to placing the queen
				p[k]=j;
				if(judge(p, k))
				{
					// recurse to next position
					Queen(p, n, k+1);
				}
			}
		}
	}
	public static void main(String[] args)
	{
		System.out.println("Please enter the number of queens: ");
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int []p=new int[n];
		Queen(p,n,0);
		//Print the result, if you just print this count, the program will run faster.
		System.out.println(n+"Solutions to Queen's Problem:"+num+"kinds");
	}

}

  The code of the algorithm is like this. The main body of the algorithm is still hard to think about. After thinking about it for a while, I feel that there are still some problems, but the result of the code execution is correct, so I don’t think about it anymore. Pay attention to the size of the pointer of the for loop in the algorithm, and think about it here, although only a simple one-dimensional array. Let me talk about some of my ideas below. This algorithm is a simple recursive solution. To put it more clearly, it is the exhaustive method. This is the inadequacy of this algorithm. Just after a simple enumeration, there is no function restriction. This is somewhat different from the idea of ​​backtracking. The idea of ​​backtracking is that the main body of the algorithm also has function restrictions, and some erroneous subtrees of the following solutions are directly removed. This algorithm does not achieve this step, and the implementation of the algorithm is still very large. It takes about 100 seconds to solve the problem of 16 queens, which is the approximate limit of the algorithm (this is also seen on the Internet). I am still a rookie, and I just think about it now. It is still necessary to understand the idea of ​​backtracking, and limit the function to the result when it is exhaustive, which is convenient for the enumeration later, and greatly speeds up the efficiency of the algorithm.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325208449&siteId=291194637