반응형
문제는 여기
퀸은 배치된 칸을 기준으로 가로,세로, 그리고 대각선 이동이 가능한 가장 가치있는 말로 다음 빨간선과 같이 움직인다.
다음은 N이 8일때 해 중의 하나이다.
만약 모든 경우의 수에 대해서 재귀를 통해 브루트포스 방식으로 구한다음에 해인지 아닌지를 말단에서 체크하게 되면, DFS가 되는데,
N=8인 경우 체스판의 칸 개수가 8x8=64개이고 이중에 8개를 고르는 조합의 수가 되므로 $_{64}C_8 = 4,426,165,368$이 되어 44억이 넘어갑니다. 이중에 92개만이 정답이죠.
가로로 겹치지 않게 한줄에 하나의 queen만 놓는식으로 가지치기(백트래킹)를 하게되면 $8^8 = 16,777,216$으로 줄어듭니다. (천6백만)
세로로도 겹치지 않게 permutation을 사용하는 백트래킹의 경우 $8! = 40,320$이 되어 훨씬 줄어듭니다.
다음과 같이 한줄씩 보면서 가로,세로,대각선 모두에 대해 백트래킹을 사용하면 5,508정도로 더 줄어듭니다.
이 문제의 경우 이정도 가지치기를 하면 제한시간내에 맞았습니다를 받을 수 있습니다.
소스코드는 다음과 같습니다.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#include <bits/stdc++.h>
using namespace std;
int N;
int vx[15+1], vy[15+1];
int go(int y, int x)
{
//check valid (back tracking)
for (int i = 0; i < y; i++) {
if (y == vy[i] || x == vx[i]) return 0; //직선겹침
if (abs(x - vx[i]) == abs(y - vy[i])) return 0; //대각겹침
}
//terminal condition
if (y == N - 1) return 1;
//now record position
vy[y] = y, vx[y] = x;
//loop
int r = 0;
for (int i = 0; i < N; i++) {
r += go(y + 1, i);
}
return r;
}
int main(void)
{
scanf("%d", &N);
int r = 0;
for (int i = 0; i < N; i++) r += go(0, i);
printf("%d\n", r);
return 0;
}
|
cs |
반응형
'Programming > Problem Solving' 카테고리의 다른 글
| 코드포스 C++ 헬퍼(VsCaide) (0) | 2020.04.02 |
|---|---|
| C++ bigint class (1) | 2020.03.30 |
| 행렬코딩 (0) | 2020.03.01 |
| C언어에서 표준입력으로 string 입력 받기 (0) | 2020.02.21 |
| 백준 팁모음 (0) | 2019.03.18 |
