본문으로 바로가기

Recursion - N Queens Problem

category Algorithm/개념 2020. 12. 8. 18:37

n queens problem

체스판에 퀸의 동선이 겹치지 않게 놓는 문제

백 트래킹

백 트래킹은 퇴각 검색이라고 해석되며 트리에서 내가 원하는 해를 검색하는 알고리즘인데

검색할 때 내가 원하지 않는 노드를 만나게 되면 그 노드와 자식들은 검색할 필요가 없으므로

그 노드의 부모로 퇴각한 후 다른 자식을 검사하러 간다

접근 방법

2차원 배열을 선언하고 시작하려 했지만 필요가 없었다

어짜피 한줄에 하나의 말만 놓이게 되기 때문에 인덱스가 행을 안의 값이 열을 나타내는 것

예를 들어 board[2] = 3 은 3번째 줄에 3번째 열에 퀸이 있는 것

board = [1,3,3,3]은 보드판으로 나타내면 아래와 같다

1 0 0 0
0 0 1 0
0 0 1 0
0 0 1 0

내가 푼 코드

나는 풀다가 포기하고 결국 영상을 끝까지 봤다..

베이스 케이스를 구현하지도 않고 시작했기 때문일까 갈피를 못 잡고 흐지부지..

노드의 유망성 검사도 제대로 이해하지 못해서 promising도 맞추질 못했다

코드 구현

function promising(level) {

    for(let i=0; i<level;i++){
        if(board[i] === board[level]) return false;

        if(level - i === Math.abs(board[i]-board[level])) return false;
    }

    return true;
}

function queen(level) {
    if (!promising(level-1)) return false;
    if (level === n) return true;

    for (let i = 1; i <= n; i++) {
        board[level] = i;
        if (queen(level + 1)) return true;
    }
    return false;
}

    if (!promising(level-1)) return false;
    if (level === n) return true;

두개의 베이스 케이스

하나는 노드의 유망성을 검사해 유망하지 않으면 백, 다른 하나는 백 하지 않고 끝까지 가서 퀸들을 모두 놓았을 때 true를 반환하게 했다

    for(let i=0; i<level;i++){
        if(board[i] === board[level]) return false;

        if(level - i === Math.abs(board[i]-board[level])) return false;
    }

유망성 검사 코드

이전에 놓았던 말들의 위치와 가장 최근에 놓은 말의 위치를 비교해서

if(board[i] === board[level]) return false;

직선상에 있는지

    if(level - i === Math.abs(board[i]-board[level])) return false;

대각선상에 있는지

검사하는 코드이다

    for (let i = 1; i <= n; i++) {
        board[level] = i;
        if (queen(level + 1)) return true;
    }

현재 level에 말을 놔둔 후 level에 +1을 한 뒤 재귀호출하는 부분

'Algorithm > 개념' 카테고리의 다른 글

에라토스테네스의 체  (0) 2020.12.13
Recursion - 순열  (0) 2020.12.11
Recursion - 멱집합  (0) 2020.12.09
Recursion - 미로 찾기  (0) 2020.12.06
Recursion  (0) 2020.12.05