| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
Tags
- Strongly Connected Component
- ccw 알고리즘
- LCA
- 2-SAT
- PROJECT
- 비트마스킹
- Github
- R 그래프
- 자바스크립트
- localstorage
- 그래프 탐색
- 트라이
- 이분 탐색
- MongoDB
- 분리 집합
- Behavior Design Pattern
- 게임 서버 아키텍처
- 벨만-포드
- map
- 비트필드를 이용한 dp
- DP
- 최소 공통 조상
- Express.js
- trie
- 강한 연결 요소
- Prisma
- SCC
- JavaScript
- Binary Lifting
- Spin Lock
Archives
- Today
- Total
dh_0e
[PS] 비숍 / C++ (백준 1799번) 본문
N-Queen 문제와 동일하게 백트래킹으로 해결해야 하는 문제지만 런타임을 더 줄여야 한다.
모든 경우의 수를 탐색하면, k를 nxn 체스판에서 최대로 들어갈 수 있는 비숍의 개수라 놓고 시간 복잡도가 $O(2^k)$가 나올 것이라 예상했다. 10x10 체스판에 최대로 놓을 수 있는 비숍의 수(k)가 18개라 $2^{18}$은 10억을 넘지 않기 때문에 10초 안에 풀 수 있을 것 같았지만 발상 오류였다. 실제론 $O(2^{n*n})$
풀이 과정
결국 정해를 찾아보고 문제를 해결했다. 시간을 줄일 수 있는 방법은 $n$x$n$ 체스판을 흑, 백 2개의 $(n/2)$x$(n/2)$ 체스판으로 분할하여 각각 백트래킹을 수행하여 구한 최대로 놓을 수 있는 비숍의 개수를 합치는 것이었다. 이렇게 되면 각 백트래킹에서 $O(2^{(n/2)*(n/2)})$의 시간 복잡도가 소요되며 최대 n값인 10이 들어가도 $2^{25}$은 10억(≒$2^{30}$)을 넘지 않기 때문에 시간 안에 AC를 받을 수 있다.
본인은 다음 비숍이 올 수 있는 자리를 찾을 때, find_next() 함수를 호출하게끔 코드를 짜놓아서, 이 부분만 수정하였다.
이전 find_next() 함수 (시간 초과)
pair<int, int> find_next(int x, int y)
{
while (1) {
if (x + 1 > n) { y++; x = 1; }
else x++;
if (y > n)break;
if (atk[y][x] == 0 && bi[y][x])
return make_pair(x, y);
}
return make_pair(-1, -1);
}
AC 코드(흑, 백 체스판 분리)
#include<iostream>
#include<algorithm>
using namespace std;
int n, dap = 0, white = 0, black = 0;
int bi[11][11], atk[11][11];
pair<int, int> find_next(int x, int y)
{
while (1) {
if (x + 2 > n) { y++; x = x % 2 == 0 ? 1 : 2; }
else x += 2;
if (y > n)break;
if (atk[y][x] == 0 && bi[y][x])
return make_pair(x, y);
}
return make_pair(-1, -1);
}
void attack_execute(int x, int y)
{
for (int i = 1; i + y <= n && i + x <= n; i++)
atk[i + y][i + x]++;
for (int i = 1; i + y <= n && x - i > 0; i++)
atk[i + y][x - i]++;
return;
}
void attack_release(int x, int y)
{
for (int i = 1; i + y <= n && i + x <= n; i++)
atk[i + y][i + x]--;
for (int i = 1; i + y <= n && x - i > 0; i++)
atk[i + y][x - i]--;
return;
}
void f(int x, int y, int count)
{
if (dap < count + 1)dap = count + 1;
attack_execute(x, y);
pair<int, int> next = find_next(x, y);
if (next.first != -1)
f(next.first, next.second, count + 1);
attack_release(x, y);
next = find_next(x, y);
if (next.first == -1) return;
f(next.first, next.second, count);
return ;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)scanf("%d", &bi[i][j]);
}
pair<int, int> next = find_next(-1, 1); // 백 체스판 (1로 시작)
if (next.first != -1)f(next.first, next.second, 0);
white = dap;
dap = 0;
next = find_next(0, 1); // 흑 체스판 (2로 시작)
if (next.first != -1)f(next.first, next.second, 0);
black = dap;
printf("%d\n", white + black);
return 0;
}'Problem Solving > Baekjoon' 카테고리의 다른 글
| [PS] 전깃줄-2 / C++ (백준 2568번) (0) | 2026.01.15 |
|---|---|
| [PS] 아기 상어 / C++ (백준 16236번) (0) | 2026.01.05 |
| [PS] 피보나치 수 6 / C++ (백준 11444번) (0) | 2025.12.26 |
| [PS] 골목길 / C++ (백준 1738번) (0) | 2025.12.22 |
| [PS] 오민식의 고민 / C++ (백준 1219번) (0) | 2025.12.18 |