NQUEEN 문제 질문합니다.

  • chatterboy
    chatterboy

    NQUEEN

    재귀호출을 할 때마다 하나의 행에 대해서 가능한 모든 위치를 탐색하도록 구현을 했습니다. 구현한 함수가 nqueen(row)입니다.

    그리고 한 행에서 퀸을 놓을 수 있는 위치를 찾았다면 (y,x)라고 할 때 현재 행보다 큰 행들에 대해서 양 대각선과 아랫 방향으로 색칠을 했습니다. 구현한 함수가 paint(y, x, state)입니다. state에 따라서 색칠하고 지우고를 수행하도록 했습니다.

    4, 5 까지는 정상적으로 출력되나 싶었지만 8을 넣어보니 말도 안되는 수가 출력이 되서 .. 그 이유를 모르겠습니다.

    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <iostream>
    #include <limits>
    #include <map>
    #include <set>
    #include <utility>
    #include <vector>
    #include <queue>
    
    #define TEST1
    
    using namespace std;
    
    #define atoi(a) (a-'a')
    
    vector < vector <int> > board;
    
    // state = 0이면 0으로 1이면 1로 칠한다
    void paint(int y, int x, int state)
    {
        // (y+1,x), (y+2,x) ... (y+k,x) ... (n,x)
        for (int k = 1; y + k < board.size(); k++)
            if (state == 1)
                board[y+k][x] = 1;
            else
                board[y+k][x] = 0;
    
        // (y+1,x+1), (y+2,x+2) ... (y+k,x+k) ... (n,n)
        for (int k = 1; x + k < board.size() && y + k < board.size(); k++)
            if (state == 1)
                board[y+k][x+k] = 1;
            else
                board[y+k][x+k] = 0;
    
        // (y+1,x-1), (y+2,x-2) ... (y+k,x-k) ... (n,1)
        for (int k = 1; x - k > -1 && y + k < board.size(); k++)
            if (state == 1)
                board[y+k][x-k] = 1;
            else
                board[y+k][x-k] = 0;
    }
    
    // 현재 선택된 row에서 퀸을 놓을 수 있는지 검사한다
    // 가능한 경우들이 존재하면 모든 경우를 확인한다
    // 가능한 하나의 경우를 선택 후 다음 재귀 호출한다
    int nqueen(int row)
    {
        // 놓을 수 있는 자리가 있는지 확인
        int valid = false;
        for (int i = 0; i < board[row].size(); i++)
            if (board[row][i] == 0)
                valid = true;
        if (!valid)
            return 0;
        if (valid && row == board.size()-1)
            return 1;
    
    
        // 가능한 모든 경우 탐색
        int possible = 0;
        for (int i = 0; i < board[row].size(); i++)
        {
            if (board[row][i] == 0)
            {
                paint(row, i, 1);
    
                possible += nqueen(1 + row);
    
                paint(row, i, 0);
            }
        }
    
        return possible;
    }
    
    int MAIN()
    {
    
        vector <int> res;
        int tc; cin >> tc;
        while (tc--)
        {
            int n; cin >> n;
            board = vector < vector <int> > (n, vector <int> (n) );
    
            res.push_back(nqueen(0) );
        }
        for (int i = 0; i < res.size(); i++)
            cout << res[i] << endl;
        return 0;
    }
    

    10년 전
2개의 댓글이 있습니다.
  • Being
    Being

    어떤 칸에 두 개 이상의 퀸이 영향을 미칠 때, paint()에서 어떻게 지워낼지 생각해 보세요.


    10년 전 link
  • chatterboy
    chatterboy

    감사합니다 왜 잘못된 것인지 알겠습니다.


    10년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.