카테고리 없음
[JAVA/자바] 백준 BAEKJOON 1063번 킹
remazitensi
2024. 8. 22. 03:06
문제링크
https://www.acmicpc.net/problem/1063


문제 풀이
첫 번째 풀이법 (BufferedReader 및 BufferedWriter 사용)
- 입력 처리:
- BufferedReader를 사용하여 킹과 돌의 초기 위치, 그리고 이동 명령어 개수를 읽어옵니다.
- 킹과 돌의 위치는 문자와 숫자로 주어지므로, 이를 행과 열의 좌표로 변환합니다. 변환 과정에서 indexToThing 메서드를 사용하여 'H1'을 (0, 7)로 변환합니다.
- 명령어 처리:
- 이동 명령어들을 배열에 저장하고, 각 명령어를 처리합니다.
- 각 명령어에 대해 방향을 결정하고, 킹과 돌이 이동해야 하는지 확인합니다.
- isThereStone 메서드를 통해 킹의 이동 방향에 돌이 있는지 확인하고, 돌도 함께 이동해야 하는지 판단합니다.
- 이동 유효성 검사:
- 킹과 돌이 이동할 새로운 위치가 체스판 범위 내에 있는지 확인합니다. 체스판 범위를 벗어날 경우 해당 이동은 무시합니다.
- move 메서드를 사용하여 킹과 돌을 이동시키고, 유효한 이동만 반영합니다.
- 결과 출력:
- 최종적으로 킹과 돌의 위치를 체스판의 문자와 숫자 형식으로 변환하여 출력합니다. 변환 과정에서는 thingToIndex 메서드를 사용하여 좌표를 다시 문자와 숫자 형식으로 변환합니다.
두 번째 풀이법 (HashMap 사용)
- 입력 처리:
- Scanner를 사용하여 킹과 돌의 초기 위치, 그리고 이동 명령어 개수를 읽어옵니다.
- 킹과 돌의 위치를 알파벳과 숫자 형식에서 체스판의 좌표로 변환합니다. 예를 들어 'H1'을 (7, 0)으로 변환합니다.
- 방향 변환:
- 방향에 따른 좌표 변화량을 HashMap에 저장하여, 각 명령어가 어떻게 좌표를 변화시키는지 정의합니다. 예를 들어 "R"은 (0, 1)로 좌표를 오른쪽으로 이동시킵니다.
- 이동 처리:
- 각 명령어를 읽고, 방향에 따른 좌표 변화를 적용하여 킹과 돌의 새로운 위치를 계산합니다.
- 킹의 새로운 위치가 체스판 내에 있는지 확인하고, 만약 킹이 이동한 위치에 돌이 있으면 돌도 이동시킵니다. 돌의 새로운 위치도 체스판 내에 있는지 확인합니다.
- 결과 출력:
- 최종적으로 킹과 돌의 위치를 체스판의 문자와 숫자 형식으로 변환하여 출력합니다. 이 과정에서 좌표를 다시 문자와 숫자 형식으로 변환합니다.
코드
- 첫 번째 방법은 BufferedReader와 BufferedWriter를 사용하여 빠르게 입력과 출력을 처리하며, 직접적으로 방향 변화량을 배열로 관리하고, 킹과 돌의 위치를 객체로 처리
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 입력 받기
String kingPos = scanner.next(); // 킹의 위치
String stonePos = scanner.next(); // 돌의 위치
int n = scanner.nextInt(); // 움직이는 횟수
// 방향에 따른 좌표 변화량을 맵에 저장
Map<String, int[]> directions = new HashMap<>();
directions.put("R", new int[]{0, 1});
directions.put("L", new int[]{0, -1});
directions.put("B", new int[]{-1, 0});
directions.put("T", new int[]{1, 0});
directions.put("RT", new int[]{1, 1});
directions.put("LT", new int[]{1, -1});
directions.put("RB", new int[]{-1, 1});
directions.put("LB", new int[]{-1, -1});
// 킹과 돌의 초기 위치를 좌표로 변환
int kingX = kingPos.charAt(1) - '1';
int kingY = kingPos.charAt(0) - 'A';
int stoneX = stonePos.charAt(1) - '1';
int stoneY = stonePos.charAt(0) - 'A';
// 움직임 처리
for (int i = 0; i < n; i++) {
String move = scanner.next();
int[] dir = directions.get(move);
int newKingX = kingX + dir[0];
int newKingY = kingY + dir[1];
// 킹이 이동한 위치가 체스판 안에 있을 경우
if (isInsideBoard(newKingX, newKingY)) {
// 킹의 새로운 위치가 돌의 위치와 같을 경우 돌을 이동시킴
if (newKingX == stoneX && newKingY == stoneY) {
int newStoneX = stoneX + dir[0];
int newStoneY = stoneY + dir[1];
// 돌의 새로운 위치가 체스판 안에 있어야 함
if (isInsideBoard(newStoneX, newStoneY)) {
stoneX = newStoneX;
stoneY = newStoneY;
kingX = newKingX;
kingY = newKingY;
}
} else {
kingX = newKingX;
kingY = newKingY;
}
}
}
// 최종 위치를 알파벳+숫자 형식으로 변환하여 출력
System.out.println((char) (kingY + 'A') + "" + (kingX + 1));
System.out.println((char) (stoneY + 'A') + "" + (stoneX + 1));
}
// 체스판 안에 있는지 확인하는 메서드
private static boolean isInsideBoard(int x, int y) {
return x >= 0 && x < 8 && y >= 0 && y < 8;
}
}
- 두 번째 방법은 Scanner와 HashMap을 사용하여 입력과 방향 변화를 간단하게 처리하고, 킹과 돌의 위치를 직접 좌표로 계산하여 이동합니다. 이 방법은 코드가 더 간결하고, HashMap을 통해 방향 변화를 매핑
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
// 킹과 돌의 위치를 표현하는 내부 클래스
static class Thing {
int r, c;
// 생성자: 행과 열 좌표를 받아서 초기화
public Thing(int r, int c) {
this.r = r;
this.c = c;
}
}
static Thing king, stone; // 킹과 돌의 위치를 저장하는 객체
static String[] cmds; // 이동 명령어들을 저장하는 배열
static int N; // 명령어 개수
static int[] dr = {0, -1, -1, -1, 0, 1, 1, 1}; // 행 변화량: L, LT, T, RT, R, RB, B, LB 순
static int[] dc = {-1, -1, 0, 1, 1, 1, 0, -1}; // 열 변화량: L, LT, T, RT, R, RB, B, LB 순
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// 입력: 킹과 돌의 초기 위치 및 이동 명령어 개수
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
king = indexToThing(st.nextToken()); // 킹의 위치를 좌표로 변환
stone = indexToThing(st.nextToken()); // 돌의 위치를 좌표로 변환
N = Integer.parseInt(st.nextToken()); // 이동 명령어 개수
cmds = new String[N];
for (int i = 0; i < N; i++) {
String cmd = br.readLine();
int direction = getDirection(cmd); // 명령어를 방향 인덱스로 변환
boolean withStone = isThereStone(direction); // 이동할 방향에 돌이 있는지 확인
move(direction, withStone); // 킹과 돌을 이동
}
// 최종 위치 출력
String k = thingToIndex(king); // 킹의 위치를 알파벳+숫자 형식으로 변환
String s = thingToIndex(stone); // 돌의 위치를 알파벳+숫자 형식으로 변환
bw.write(k + "\n" + s);
bw.flush();
bw.close();
br.close();
}
// 체스판 위치를 행과 열 좌표로 변환하는 메서드 (예: H1 -> r, c 좌표)
static Thing indexToThing(String index) {
int c = index.charAt(0) - 'A'; // 열 계산
int r = 8 - (index.charAt(1) - '0'); // 행 계산
return new Thing(r, c);
}
// 행과 열 좌표를 체스판 위치로 변환하는 메서드 (예: r, c 좌표 -> H1)
static String thingToIndex(Thing thing) {
char c = (char) (thing.c + 'A'); // 열을 알파벳으로 변환
char r = (char) (8 - thing.r + '0'); // 행을 숫자로 변환
return "" + c + r;
}
// 명령어를 이동 방향 인덱스로 변환하는 메서드
static int getDirection(String cmd) {
switch (cmd) {
case "L": return 0;
case "LT": return 1;
case "T": return 2;
case "RT": return 3;
case "R": return 4;
case "RB": return 5;
case "B": return 6;
default: return 7; // "LB"
}
}
// 킹이 이동할 방향에 돌이 있는지 확인하는 메서드
static boolean isThereStone(int direction) {
int nr = king.r + dr[direction];
int nc = king.c + dc[direction];
return stone.r == nr && stone.c == nc; // 이동할 위치에 돌이 있으면 true 반환
}
// 킹과 돌을 이동시키는 메서드
static void move(int direction, boolean withStone) {
if (withStone) { // 돌도 함께 움직여야 할 때
int nr = stone.r + dr[direction];
int nc = stone.c + dc[direction];
// 돌이 체스판을 벗어나지 않으면 이동
if (nr >= 0 && nr < 8 && nc >= 0 && nc < 8) {
stone.r = nr;
stone.c = nc;
} else {
return; // 돌이 벗어나면 이동 무시
}
}
// 킹이 체스판을 벗어나지 않으면 이동
int nr = king.r + dr[direction];
int nc = king.c + dc[direction];
if (nr >= 0 && nr < 8 && nc >= 0 && nc < 8) {
king.r = nr;
king.c = nc;
}
}
}