jo16
좌충우돌 기록기
jo16
전체 방문자
오늘
어제
  • 분류 전체보기 (30)
    • NLP (1)
    • 일반 (0)
    • 취업 (1)
    • 42seoul (1)
    • 운영체제 (1)
    • 컨퍼런스 (1)
    • 데이터베이스시스템 (5)
    • 알고리즘 (10)
    • 회고 (0)
    • Deep Learning Specializatio.. (9)
      • Neural Networks and Deep Le.. (4)
      • Improving Deep Neural Netwo.. (3)
      • Convolutional Neural Networ.. (0)
      • Sequence Models (0)
      • Structing Machine Learning .. (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 네이버 deview
  • 강의정리
  • Computer Graphics
  • 복습
  • mlx
  • 딥러닝
  • KEY
  • relational model
  • 머신러닝
  • 데이터베이스시스템
  • 개발자컨퍼런스
  • dbms
  • NAVERDEVIEW2023
  • Ai
  • 삼성SW역량테스트
  • 첫 취준
  • cs
  • raycasting
  • Cub3D
  • relational algebra
  • 42seoul
  • 삼성대학생인턴
  • 컴퓨터공학

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
jo16

좌충우돌 기록기

백준 9663 N-Queen (C++)
카테고리 없음

백준 9663 N-Queen (C++)

2024. 3. 22. 22:22

문제설명

https://www.acmicpc.net/problem/9663

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

문제 해결 

백트래킹(DFS)을 이용해서 푸는 문제이다. 한 step당 하나의 퀸을 일단 두고, 조건에 만족하면 다음 step으로 넘어가는 방식이다. 

주의할 점은 두 가지이다.

1. visit 배열을 두어 현재 둔 위치를 체크해두되, DFS 재귀문 호출 뒤에 다시 풀어준다. 

2. 대각선 인덱스 헷갈리지 않게 조심한다. 대각선 기준으로 찾을 때, 현재 step 이전에 y가 더 큰 경우도 고려해주어야 한다. 

 

트러블 슈팅 + 개선안 

나는 확인하는 체스판 배열 (v배열)을 2차원으로 두어도 시간 초과가 나지 않았는데, 그 이유는 현재 퀸 위치가 x, y라면, 현재 위치 기준으로 (x - 1, y - 1), (x - 2, y - 2) .. 이러한 식으로 for문을 한번만 사용하여 풀었기 때문이다. 그래서 더더욱.. 풀면서 2차원으로 v배열을 둘 필요가 없다는 사실을 깨달았다. 인덱스 계산하다가 조금 꼬여서 그 부분에서 시간을 조금 사용하였다.

 

1차원 배열 버전으로도 풀어보고 싶어서 두 번 풀었다. v 배열을 1차원으로 두고 각 배열에 현재 queen의 위치를 적어둔다면, 훨씬 간편하게 이 문제를 해결할 수 있다. 대각선 인덱스 구하는 노가다를 안해도 된다.. 그리고 두 버전으로 풀어보니 시간도 2배정도 준 모습을 확인할 수 있었다. 

기존 풀이

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
int v[16][16] = {0, };
int n;
int sum = 0;

int check(int x, int y) 
{
    for (int i = 1; i <= max(x, y); i++)
    {
        if ((x - i) >= 0 && (y - i) >= 0)
            if (v[x- i][y - i] == 1)
                return (0);
        if ((x - i) >= 0 && (y + i) < n)
            if (v[x - i][y + i] == 1)
                return (0);
    }
    for (int i = 0; i < x; i++)
        if (v[i][y] == 1) //세로줄 검사 
            return (0);      
    return (1);
}

void dfs(int step)
{
    if (step == n)
    {
        sum++;
        return ;
    }
    for (int i = 0; i < n; i ++)
    {
        v[step][i] = 1;
        if (check(step, i))
            dfs(step + 1);
        v[step][i] = 1;
    }
}
int main(void)
{
    cin >> n;
    dfs(0);
    cout << sum << "\n";
    return (0);
}

 

v배열을 1차원으로 줄여 개선한 풀이 

 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
int v[16] = {0, };
int n;
int sum = 0;

int check(int step) 
{
    for (int i = 0; i < step; i++)
    {
        if (abs(v[step] - v[i]) == step - i)
            return (0);
        if (v[step] == v[i])
            return (0);
    }
    return (1);
}

void dfs(int step)
{
    if (step == n)
    {
        sum++;
        return ;
    }
    for (int i = 0; i < n; i ++)
    {
        v[step] = i;
        if (check(step))
            dfs(step + 1);
    }
}
int main(void)
{
    cin >> n;
    dfs(0);
    cout << sum << "\n";
    return (0);
}

 

결과

    jo16
    jo16
    공부한 것들을 기록합니다.

    티스토리툴바