Coding/알고리즘
[알고리즘 TIL] Q1986(구현)
kangplay
2025. 5. 11. 22:20
문제
https://www.acmicpc.net/problem/1986

트러블 슈팅
1. 배열 인덱스 접근 시 조건 순서 문제
퀸의 위협 영역을 구현할 때, 아래와 같은 코드에서 ArrayIndexOutOfBoundsException이 발생했다.
while (!board[i - count][j].equals("Pawn") && i - count >= 0)
여기서 i - count가 음수인 상태에서 배열 접근이 먼저 실행되었기 때문에 런타임 오류가 발생했다. 조건 순서를 반드시 인덱스 유효성 검사 → 배열 접근 순으로 바꿔야 한다.
while (i - count >= 0 && board[i - count][j].equals("Safe")) {
...
}
2. 나이트 이동 구현 중 조건문 반복 → 방향 배열로 리팩토링
나이트의 이동 범위를 다음처럼 8개의 if 문으로 작성했는데, 코드 중복이 심하고 유지보수가 어려웠다.
if (i - 2 > -1 && j - 1 > -1) ...
if (i - 2 > -1 && j + 1 < m) ...
...
나이트의 모든 이동 방향을 dx, dy 배열로 선언한 후, 반복문으로 처리하도록 리팩토링했다.
private static final int[][] KNIGHT_MOVES = {
{-2, -1}, {-2, 1}, {2, -1}, {2, 1},
{-1, -2}, {-1, 2}, {1, -2}, {1, 2}
};
for (int[] move : KNIGHT_MOVES) {
int ni = i + move[0];
int nj = j + move[1];
if (ni >= 0 && ni < n && nj >= 0 && nj < m && board[ni][nj].equals("Safe")) {
board[ni][nj] = "Unsafe";
}
}
퀸도 다음과 같이 리팩토링할 수 있다.
// 8방향: ↖ ↑ ↗ → ↘ ↓ ↙ ←
int[] dx = {-1, 0, 1, 1, 1, 0, -1, -1};
int[] dy = {-1, -1, -1, 0, 1, 1, 1, 0};
for (int dir = 0; dir < 8; dir++) {
int ny = i, nx = j;
while (true) {
ny += dy[dir];
nx += dx[dir];
if (ny < 0 || ny >= n || nx < 0 || nx >= m) break; // 경계
if (!board[ny][nx].equals("Safe")) break; // 말 or Pawn이 막으면 멈춤
board[ny][nx] = "Unsafe";
}
}
-> 시뮬레이션 문제에서 방향이 정해진 이동은 무조건 dx/dy 배열로 추상화하자 !!
구현
import java.io.*;
public class Q1986 {
static BufferedReader br;
static BufferedWriter bw;
static String[][] chessBoard;
static int n, m;
public static void main(String[] args) throws IOException {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String[] inputStrArr = br.readLine().split(" ");
n = Integer.parseInt(inputStrArr[0]);
m = Integer.parseInt(inputStrArr[1]);
chessBoard = new String[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
chessBoard[i][j] = "Safe";
}
}
getChessPiecesData("Queen");
getChessPiecesData("Knight");
getChessPiecesData("Pawn");
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
String chess = chessBoard[i][j];
switch (chess) {
case "Queen":
checkUnSafeByQueen(i, j);
break;
case "Knight":
checkUnSafeByKnight(i, j);
break;
}
}
}
int result = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (chessBoard[i][j].equals("Safe")) result++;
}
}
bw.write(result+"");
bw.flush();
bw.close();
br.close();
}
private static void checkUnSafeByKnight(int i, int j) {
if (i - 2 > -1 && j - 1 > -1 && chessBoard[i - 2][j - 1].equals("Safe")) chessBoard[i - 2][j - 1] = "Unsafe";
if (i - 2 > -1 && j + 1 < m && chessBoard[i - 2][j + 1].equals("Safe")) chessBoard[i - 2][j + 1] = "Unsafe";
if (i + 2 < n && j - 1 > -1 && chessBoard[i + 2][j - 1].equals("Safe")) chessBoard[i + 2][j - 1] = "Unsafe";
if (i + 2 < n && j + 1 < m && chessBoard[i + 2][j + 1].equals("Safe")) chessBoard[i + 2][j + 1] = "Unsafe";
if (i - 1 > -1 && j - 2 > -1 && chessBoard[i - 1][j - 2].equals("Safe")) chessBoard[i - 1][j - 2] = "Unsafe";
if (i - 1 > -1 && j + 2 < m && chessBoard[i - 1][j + 2].equals("Safe")) chessBoard[i - 1][j + 2] = "Unsafe";
if (i + 1 < n && j - 2 > -1 && chessBoard[i + 1][j - 2].equals("Safe")) chessBoard[i + 1][j - 2] = "Unsafe";
if (i + 1 < n && j + 2 < m && chessBoard[i + 1][j + 2].equals("Safe")) chessBoard[i + 1][j + 2] = "Unsafe";
}
private static void checkUnSafeByQueen(int i, int j) {
int count = 1;
while (i - count > -1 && !(chessBoard[i - count][j].equals("Queen") || chessBoard[i - count][j].equals("Knight") || chessBoard[i - count][j].equals("Pawn"))) {
chessBoard[i - count][j] = "Unsafe";
count++;
}
count = 1;
while ( i + count < n && !(chessBoard[i + count][j].equals("Queen") || chessBoard[i + count][j].equals("Knight") || chessBoard[i + count][j].equals("Pawn"))) {
chessBoard[i + count][j] = "Unsafe";
count++;
}
count = 1;
while (j - count > -1 && !(chessBoard[i][j - count].equals("Queen") || chessBoard[i][j - count].equals("Knight") || chessBoard[i][j - count].equals("Pawn"))) {
chessBoard[i][j - count] = "Unsafe";
count++;
}
count = 1;
while (j + count < m && !(chessBoard[i][j + count].equals("Queen") || chessBoard[i][j + count].equals("Knight") || chessBoard[i][j + count].equals("Pawn"))) {
chessBoard[i][j + count] = "Unsafe";
count++;
}
count = 1;
while (i - count > -1 && j - count > -1 && !(chessBoard[i - count][j - count].equals("Queen") || chessBoard[i - count][j - count].equals("Knight") || chessBoard[i - count][j - count].equals("Pawn"))) {
chessBoard[i - count][j - count] = "Unsafe";
count++;
}
count = 1;
while (i + count < n && j + count < m && !(chessBoard[i + count][j + count].equals("Queen") || chessBoard[i + count][j + count].equals("Knight") || chessBoard[i + count][j + count].equals("Pawn"))) {
chessBoard[i + count][j + count] = "Unsafe";
count++;
}
count = 1;
while (i - count > -1 && j + count <m && !(chessBoard[i - count][j + count].equals("Queen") || chessBoard[i - count][j + count].equals("Knight") || chessBoard[i - count][j + count].equals("Pawn"))) {
chessBoard[i - count][j + count] = "Unsafe";
count++;
}
count = 1;
while (i + count < n && j - count >-1 && !(chessBoard[i + count][j - count].equals("Queen") || chessBoard[i + count][j - count].equals("Knight") || chessBoard[i + count][j - count].equals("Pawn"))) {
chessBoard[i + count][j - count] = "Unsafe";
count++;
}
}
private static void getChessPiecesData(String pieceName) throws IOException {
String[] inputStrArr = br.readLine().split(" ");
int count = Integer.parseInt(inputStrArr[0]);
for (int i = 0; i < count; i++) {
int row = Integer.parseInt(inputStrArr[i * 2 + 1]) - 1;
int col = Integer.parseInt(inputStrArr[i * 2 + 2]) - 1;
chessBoard[row][col] = pieceName;
}
}
}