SW Expert Academy 15612_체스판 위의 룩 배치 문제풀이 in C++
문제 URL
문제 요구사항
- 8 x 8 크기의 체스판 위의 몇 개의 칸에 룩(rook)이 놓여 있다.
- 각 칸에는 최대 1개의 룩을 놓을 수 있으므로, 체스판 위에는 0개 이상 64개 이하의 룩이 놓여 있는 것이다.
- 이때, 현재 체스판의 배치가 다음 조건을 모두 만족하는지를 판별하는 프로그램을 작성하라.
- 정확히 8개의 룩이 있어야 한다.
- 모든 룩은 서로 공격할 수 없어야 한다. 즉, 서로 다른 두 룩은 같은 열에 있거나 같은 행에 있으면 안 된다.
[입력]
- 첫 번째 줄에 테스트 케이스의 수 T가 주어진다.
- 각 테스트 케이스는 여덟 개의 줄로 이루어지며, 각 줄에는 길이가 8인 ‘O’ 또는 ‘.’로 구성된 문자열이 주어진다.
- i번째 줄의 j번째 글자는, 체스판의 i행 j열에 룩이 하나 놓여 있다면 ‘O’, 아무것도 놓여 있지 않다면 ‘.’이다.
[출력]
- 각 테스트 케이스마다, 주어진 체스판의 배치가 주어진 모든 조건을 만족한다면 ‘yes’를, 하나라도 만족하지 않는다면 ‘no’를 출력한다.
접근 방법
- Queue를 생성해, 맵 정보를 입력 받을 때, rock ( ‘O’ )를 만나면 해당 Queue에 좌표를 넣고, Queue 사이즈가 8이 아니라면 바로 결과를 출력할 수 있게 하고, 8이라면 Queue의 각 좌표들을 DFS 탐색 수행한다.
풀이 순서
- TC를 입력 받고, 해당 test_case의 맵 정보를 입력 받는다.
- 이 때, 입력 받은 맵 정보의 값이 rock( ‘O’ ) 이라면 그 좌표를 Queue에 넣는다.
- Queue의 사이즈가 8이라면 DFS 탐색을, 아니라면 곧바로 no를 출력하도록 한다.
- checkRock에 false 값을 넣어 초기화 하고, DFS 탐색을 수행하며, 수행 중 rock을 발견해 checkRock 값이 true로 바꼈다면, 곧바로 종료한다.
- 이와 같은 작업 반복 후, checkRock이 true라면 no를, 아니라면 yes를 출력한다.
- test_case 이와 같은 작업 반복
소스코드
#include <iostream>
#include <queue>
using namespace std;
char map[8][8];
int dx[] = { -1, 0, 1, 0 };
int dy[] = { 0, 1, 0, -1 };
bool checkRook = true;
void dfs(pair<int, int> coordi, int dir) {
int nx = coordi.first + dx[dir];
int ny = coordi.second + dy[dir];
if (nx >= 0 && ny >= 0 && nx < 8 && ny < 8) {
if (map[nx][ny] == 'O')
checkRook = true;
else {
dfs({ nx, ny }, dir);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int TC;
cin >> TC;
for (int test_case = 1; test_case <= TC; test_case++) {
checkRook = true;
queue<pair<int, int>> q;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
cin >> map[row][col];
if (map[row][col] == 'O') {
q.push({ row, col });
}
}
}
if (q.size() == 8) {
checkRook = false;
while (!q.empty()) {
for (int i = 0; i < 4; i++) {
dfs(q.front(), i);
}
q.pop();
if (checkRook)
break;
}
}
if (checkRook)
cout << "#" << test_case << " no\n";
else
cout << "#" << test_case << " yes\n";
}
return 0;
}