Programmers - Lv3 N-Queen


検索ルール

  • Queenは上下左右および全方向の直線対角線移動が可能です.

  • 1.上、下|左、右

  • は非常に見つけやすいルールであり、Queenがある場所に存在する場合、同じ行、同じ列にQueenは存在しない.

  • 2. Positive Diagonal

  • 対角線に移動できる場合、左上、右下方向に移動することを正方向とする.
  • 行、列については、次のルールがあります.
  • 右下に移動すると、列は+1|行は+1(左上方向も記号を変更しますが、同じ)となり、マイナス記号は常に同じになります.
  • したがって、(行-列)4を実行すると、移動可能なすべての位置対角線が同じ値になります.

    3. Negative Diagonal

  • 対角線に移動できる場合、左、右方向の移動は負方向であると仮定する.
  • 同様に、次のルールを見つけることができます.
  • を右に移動すると、+1|挙動-1となり、両者の加算は常に同じである.
  • したがって、(行+列)の値は、負方向対角線の移動経路で同じになります.

    問題を解く


    上の3つのルールを使って問題を解くことができます。

  • まず、同一行にQueenが存在するはずがないので、行をチェックせずにQueenを解放した瞬間に次の行に移るように計算することで演算量を減らすことができる.
  • の最初の行については、Queenを1つずつ配置することができ、すべての場合の数は正しい.最初の行をすべて配置した後、次の行に移動すると、重複した結果が表示されます.
  • for (let i = 0; i < n; i++) {
    	// 각 index마다 Q을 배치했다고 가정하고 연산 후 넘어간다.
    	// 이는 첫 번째 행에 대한 배치이다.
    }
  • 確認が必要な条件は3つあります.(상하 | Positive | negative)で、それぞれがSetオブジェクトによって値を保存し、Set.prototype.has()でQueenを解放できるかどうかをチェックします.
  • for (let i = 0; i < n; i++) {
      const col = new Set();
      const pos = new Set();
      const neg = new Set();
    
      col.add(i);
      pos.add(0 - i);
      neg.add(0 + i);
    }
    第1行ではなく第2行からQueenの導入を開始する場合、次のようになります.そこで,重複文ではなくDFSを用いてBrute Force方式で巡回することを記述した.
    const dfs = (r, n, col, pos, neg) => {
        if (r === n) {
    			// 모든 행을 검사했을 때 처리
        } else {
    			// DFS의 파라미터로 행(r)을 전달해주고, 열(c)은 for 문으로 순회하면서 확인한다.
          for (let c = 0; c < n; c++) {
    
    				// 만약 상하, pos, neg 방향에 Queen이 존재하면 다음 열로 넘어간다.
            if (col.has(c) || pos.has(r - c) || neg.has(r + c)) {
              continue;
            }
    				
    				// 겹치지 않으면 해당 위치에서의 상하, pos, neg 포지션을 Set 객체에 추가하고,
    				// 다음 행으로 넘어간다.(재귀 호출한다.)
            col.add(c);
            pos.add(r - c);
            neg.add(r + c);
            dfs(r + 1, n, col, pos, neg);
    
    				// DFS를 재귀 호출한 후 다음 행을 확인하기 위해 다시 delete 해준다.
            col.delete(c);
            pos.delete(r - c);
            neg.delete(r + c);
          }
        }
      };

    完了したコード

    const solution = (n) => {
      let answer = 0;
    
      const dfs = (r, n, col, pos, neg) => {
        if (r === n) {
          answer += 1;
        } else {
          for (let c = 0; c < n; c++) {
            if (col.has(c) || pos.has(r - c) || neg.has(r + c)) {
              continue;
            }
    
            col.add(c);
            pos.add(r - c);
            neg.add(r + c);
            dfs(r + 1, n, col, pos, neg);
            col.delete(c);
            pos.delete(r - c);
            neg.delete(r + c);
          }
        }
      };
    
      for (let i = 0; i < n; i++) {
        const col = new Set();
        const pos = new Set();
        const neg = new Set();
        col.add(i);
        pos.add(0 - i);
        neg.add(0 + i);
    
        dfs(1, n, col, pos, neg);
      }
    
      return answer;
    };