역 추적 방법 및 그 적용-여덟 명의 여왕의 문제

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. 역 추적

역 추적 방식은 목표를 달성하기 위해 최적의 조건에 따라 앞으로 검색하는 일종의 최적 검색 방식입니다. 특정 단계를 탐색하면 원래 선택이 좋지 않거나 목표가 달성되지 않은 것으로 확인되어 뒤로 물러나 다시 선택합니다.
통과하지 못할 경우 되돌아 가고 되돌아가는 이 기술은 역 추적 방식 이며, 역 추적 조건을 만족하는 특정 상태의 지점을 " 역 추적 지점 " 이라고합니다 .

소위 회고 적 방법, 이름은 키가 크고 생각은 매우 간단합니다. 당신을 미로에 넣고 미로에서 벗어나고 싶다고 상상 해보세요. 가장 직접적인 방법은 무엇입니까? 예, 시도하십시오. 먼저 갈 길을 선택한 다음, 갈 수없는 경우 돌아가서 다른 길을 시도하고 출구를 찾거나 모든 도로에서 벗어날 수 없을 때까지 계속 후진하십시오.

2. 여덟 여왕 문제

이것은 오래되고 잘 알려진 문제이며 역 추적 알고리즘의 전형적인 경우입니다.
이 문제는 1848 년 체스 플레이어 Max Bethel에 의해 제기되었습니다. 8 개의 퀸을 8x8 체스 판에 놓아서 서로 공격 할 수 없도록 즉, 두 명의 퀸이 같은 열에있을 수 없도록합니다. 같은 대각선에 몇 가지 방법이 있는지 물어보십시오.

정답은 92 개입니다.

자세한 내용은 다음 기사를 참조하십시오.
https://www.cnblogs.com/bigmoyan/p/4521683.html
블로거는 그림과 텍스트 로 잘 작성되어 있으며 이해하기 쉽고 재치 있고 유머러스합니다.

코드를 업로드하기 만하면 블로거의 코드를 풍부하게 만들었습니다. 스킴 수를 인쇄 할뿐만 아니라 두 가지 방법으로 배치 패턴을 출력하는 것입니다.

  • 하나는 직접 인쇄 방식입니다.
  • 다른 하나는 솔루션을 출력 목록으로 구성하는 것입니다 (LeetCode 범주의 프로그래밍 질문에 이러한 요구 사항이 있음). Leetcode51 질문 -N 퀸 질문

자바 코드

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);//以列表的形式打印方案

	}

}


또한 위 코드의 클래스 이름이 method two 라는 것을 알 수 있습니다 . 예, 다른 글쓰기 방법이 있습니다.
그러나 개인적인 감정은 위와 같이 이해하기 쉽지 않습니다.

한번 보시죠 생각은 모두 같은 회고 적 방법입니다. 차이점은 법적 배치의 판단입니다.

위의 방법은 isOk 함수를 사용하고
다음 방법은 두 개의 배열을 사용하여 주 대각선과 보조 대각선에 퀸이 있는지 여부를 저장합니다. 이 설명과 관련하여 다음 기사를 참조하십시오. 이해할 수 있어야합니다.

참조 문서 :
https://blog.csdn.net/qq_32400847/article/details/51474105#commentBox

이 코드는 Baidu Encyclopedia : The Eight Queens Problem을 참조합니다.

자바 코드


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);
	}

}

추천

출처blog.csdn.net/fxjzzyo/article/details/89107131