20436 ZOAC 3
https://www.acmicpc.net/problem/20436
문제설명
QWERTY 키보드에서 문자열을 입력하는 데 필요한 시간을 계산한다.
자음과 모음을 구분하여 각각 왼손과 오른손으로 입력한다.
문제풀이
- QWERTY 키보드에서 자음과 모음은 각각 다른 맵에 저장된다.
- 각 키는 (행, 열) 좌표로 표현되며, 키보드의 각 위치가 미리 정의되어 있다.
- 프로그램은 현재 왼손과 오른손의 위치를 추적한다.
- 입력 문자열의 각 문자에 대해:
- 문자가 자음인지 모음인지 검사한다.
- 현재 손의 위치에서 해당 문자의 위치까지의 거리를 계산한다.
- 맨해튼 거리 공식을 사용하여 거리를 계산한다. 거리=∣x1−x2∣+∣y1−y2
- 문자를 입력한 후 손의 위치를 업데이트하고, 각 문자 입력에 대해 1초를 추가한다.
O(N) 시간복잡도
메서드는 키보드의 레이아웃을 초기화하는데, 상수 시간 O(1)이 소요된다.
키보드 레이아웃은 고정되어 있다.
전체코드
import java.util.*;
import java.io.*;
public class Main {
// 3D 배열로 5x5x5 미로 정의
static int[][][] maze = new int[5][5][5], mazeCopy = new int[5][5][5];
// 회전 및 층 정보를 저장할 배열
static int arr[] = new int[5], floor[] = new int[5];
// 층 사용 여부를 체크하는 배열
static boolean check[] = new boolean[5];
// 최단 경로 결과를 저장할 변수
static int result = Integer.MAX_VALUE;
// BFS에서 사용할 카운트 배열
static int[][][] count;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 미로 정보를 입력받기
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for(int l = 0; l < 5; l++) {
// 미로의 각 위치에 대한 값을 저장
maze[i][j][l] = Integer.parseInt(st.nextToken());
}
}
}
// 층 조합을 체크하여 가능한 모든 조합 탐색
floorCheck(0);
// 최단 경로가 발견되지 않았다면 -1 출력
System.out.println((result == Integer.MAX_VALUE) ? -1 : result);
}
// 층 조합을 체크하는 메소드
static void floorCheck(int k) {
// 5개 층이 모두 선택되었을 때
if(k == 5){
// 회전 조합을 위한 백트래킹 호출
backTracking(0);
return;
}
for(int i = 0; i < 5; i++) {
if(!check[i]) { // 사용되지 않은 층일 경우
check[i] = true; // 층 사용 표시
floor[k] = i; // 층 저장
floorCheck(k + 1); // 다음 층으로 진행
check[i] = false; // 층 사용 취소
}
}
}
// 회전 조합을 체크하는 백트래킹 메소드
static void backTracking(int k) {
if(k == 5) { // 5개 회전이 모두 선택되었을 때
for(int i = 0; i < 5; i++) {
rotation(); // 선택된 층을 회전
}
// 시작점과 목표점이 열려있는지 확인
if(mazeCopy[0][0][0] == 1 && mazeCopy[4][4][4] == 1) {
bfs(); // BFS를 통해 최단 경로 탐색
if(count[4][4][4] != 0) { // 목표점에 도달한 경우
result = Math.min(result, count[4][4][4]); // 최단 경로 갱신
if(result == 12) { // 최단 경로가 12일 경우 즉시 종료
System.out.println(12);
System.exit(0);
}
}
}
return;
}
for(int i = 1; i < 5; i++) { // 회전 종류를 선택
arr[k] = i; // 현재 회전 저장
backTracking(k + 1); // 다음 회전으로 진행
}
}
// 선택된 층을 회전시키는 메소드
static void rotation() {
for(int i = 0; i < 5; i++) {
int idx = floor[i]; // 현재 층 인덱스
int rotationNum = arr[i]; // 현재 회전 번호
for(int j = 0; j < 5; j++) {
for(int l = 0; l < 5; l++) {
// 각 회전 방식에 따라 미로 복사
if(rotationNum == 1) {
mazeCopy[idx][j][l] = maze[i][j][l]; // 0도 회전
}
if(rotationNum == 2) {
mazeCopy[idx][l][4 - j] = maze[i][j][l]; // 90도 시계 방향 회전
}
if(rotationNum == 3) {
mazeCopy[idx][4 - j][4 - l] = maze[i][j][l]; // 180도 회전
}
if(rotationNum == 4) {
mazeCopy[idx][4 - l][j] = maze[i][j][l]; // 90도 반시계 방향 회전
}
}
}
}
}
// BFS로 최단 경로를 찾는 메소드
static void bfs() {
int[][] dist = {{-1, 0, 0}, {1, 0, 0}, {0, 0, -1}, {0, 0, 1}, {0, 1, 0}, {0, -1, 0}}; // 방향 배열
Queue<Pair> queue = new LinkedList<>(); // 큐 생성
boolean[][][] visit = new boolean[5][5][5]; // 방문 여부 체크 배열
count = new int[5][5][5]; // 경로 길이 저장 배열
visit[0][0][0] = true; // 시작점 방문 처리
queue.add(new Pair(0, 0, 0)); // 시작점 큐에 추가
while (!queue.isEmpty()) { // 큐가 빌 때까지 반복
Pair cur = queue.poll(); // 현재 위치 가져오기
for(int i = 0; i < 6; i++) { // 6방향 탐색
int nz = cur.z + dist[i][0];
int nx = cur.x + dist[i][1];
int ny = cur.y + dist[i][2];
// 경계를 벗어나거나 이미 방문했거나 벽인 경우 continue
if(nz < 0 || nz >= 5 || nx < 0 || nx >= 5 || ny < 0 || ny >= 5) continue;
if(visit[nz][nx][ny] || mazeCopy[nz][nx][ny] != 1) continue;
count[nz][nx][ny] = count[cur.z][cur.x][cur.y] + 1; // 경로 길이 증가
if(nz == 4 && nx == 4 && ny == 4) {
return; // 목표점에 도달하면 종료
}
visit[nz][nx][ny] = true; // 방문 처리
queue.add(new Pair(nz, nx, ny)); // 큐에 다음 위치 추가
}
}
}
// 좌표를 나타내는 Pair 클래스
public static class Pair {
int x; // x 좌표
int y; // y 좌표
int z; // z 좌표
public Pair(int z, int x, int y) {
this.x = x;
this.y = y;
this.z = z; // 생성자
}
}
}
'자료구조 > 문제풀이' 카테고리의 다른 글
[백준 JAVA] 19583 싸이버개강총회 (0) | 2024.09.27 |
---|---|
[백준 JAVA] 1743 음식물 피하기 (0) | 2024.09.26 |
[백준 JAVA] 11048 이동하기 (0) | 2024.09.26 |
[백준 JAVA]16985 Maaaaaaaaaze (1) | 2024.09.26 |
[백준 JAVA] 12933 오리 (0) | 2024.09.25 |