N-Queens Problem

  • N×N의 체스판에 N개의 퀸이 서로 위협하지 않도록(Path가 겹치지 않도록) 위치시키는 문제

4-Queens Problem의 상태공간트리


깊이우선검색(DFS)

  • 깊이우선검색(Depth First Search)을 사용하면 해답을 찾을 수 있다. 그러나 이 방법을 사용하면 해답이 될 가능성이 전혀 없는 노드의 후손(descendant) 노드까지 검색하기 때문에 비요율적이다. 위 그림에서 보면, 첫 번째 퀸이 (1, 1)에 놓일 경우 두 번째 퀸은 (2, 1)에  놓일 수 없으므로 (2, 1)의 후손노드는 검색할 필요가 없다.


노드의 유망성(Promising)

  • 전혀 해답이 나올 가능성이 없는 노드는 유망하지 않다(non-promising)고 하고, 그렇지 않으면 유망하다(promising)고 한다.
  • 위의 DFS에서 (2, 1)의 후손 노드는 non-promising하다.


되추적(Backtracking)

  • 어떤 노드의 유망성을 검사하여 유망하지 않다고 판정되면 후손 노드(서브트리)들에 대한 검색을 중지하고(Pruning), 그 노드의 부모노드로 돌아가서 다른 후손 노드에 대해 검색을 수행한다.


가지치기(Pruning)

  • 유망하지 않은 노드에 대에 진행을 하지 않는 것을 말한다.

4-Queens Problem의 되추적 상태공간트리


DFS VS Backtracking

  • 검색하는 노드 개수
    • DFS = 155 개 (전체 (1+4+16+64+256)개 중 155번째에서 솔루션을 찾게 됨)
    • Backtracking = 27 개


되추적 알고리즘의 개선

  • 유망성 여부에 대한 확인을 노드 방문 전에 실시


Java 소스코드

분석은 나중에...

public class NQueens {
  private static final int N = 4;
  private static int[] b = new int[N];
  private static int s = 0;
 
  static boolean unsafe(int y) {
    int x = b[y];
    for (int i = 1; i <= y; i++) {
      int t = b[y - i];
      if (t == x ||
          t == x - i ||
          t == x + i) {
        return true;
      }
    }
 
    return false;
  }
 
  public static void putboard() {
    System.out.println("\n\nSolution " + (++s));
    for (int y = 0; y < N; y++) {
      for (int x = 0; x < N; x++) {
        System.out.print((b[y] == x) ? "|Q" : "|_");
      }
      System.out.println("|");
    }
  }
 
  public static void main(String[] args) {
    int y = 0;
    b[0] = -1;
    while (y >= 0) {
      do {
        b[y]++;
      } while ((b[y] < N) && unsafe(y));
      if (b[y] < N) {
        if (y < N - 1) {
          b[++y] = -1;
        } else {
          putboard();
        }
      } else {
        y--;
      }
    }
  }
}


+ Recent posts