728x90
반응형
2024.11.22기준 - 실버4
728x90
백준, BEAKJOON, BOJ, JAVA, 자바
🟥 풀이
이 문제는 입력받은 행과 열, 문자열을 이용해 규현이와 승환이의 비밀 메시지를 출력하는 문제입니다.
문제 접근
- 공백과 알파벳 대문자를 0 ~ 26의 숫자로 바꿔준 뒤 5자리의 이진수로 변환하기 때문에,
key를 5자리이진수를 가지고 value로 공백 또는 알파벳대문자를 가지는 map을 먼저 생성했습니다. - 계산에 필요한 변수를 생성했습니다. (행과 열, 그리드, ...)
- 소용돌이 방향으로 이동하기 위해 이동해야되는 좌표를 동서남북으로 생성했습니다.
- 테스트 케이스의 수 만큼 반복문을 반복합니다.
- 입력받은 문자열로 그리드를 먼저 생성한 뒤 비밀 메시지를 구해 출력해줍니다.
1. 공백과 알파벳 대문자를 값으로가지는 5자리 이진수 map을 생성합니다.
// A ~ Z까지의 모든 5자리이진수를 저장합니다.
Map<String, Character> map = new LinkedHashMap<>();
map.put("00000", ' ');
for (int i = 0; i < 26; i++) {
map.put(format(i + 1), (char)('A' + i));
}
숫자를 5자리이진수로 반환하는 메소드를 생성했습니다.
// 숫자를 5자리이진수로 변환하는 메소드
private static String format (int num) {
return String.format("%05d", Integer.parseInt(Integer.toBinaryString(num)));
}
2. 계산에 필요한 변수들을 생성합니다.
// 계산에 필요한 변수를 선언
int r, c, dir, index, y, x;
String s, str;
char[] arr;
char[][] grid;
StringTokenizer st;
3. 소용돌이 방향으로 그리드를 참조하기 위해 이동할 좌표 방향을 생성했습니다.
// 동서남북 이동을 위한 좌표 설정
int[] dx = {1, 0, -1, 0};
int[] dy = {0, 1, 0, -1};
4. 테스트 케이스의 개수만큼 반복문을 돌려줍니다.
4-1. 입력받은 데이터를 가지고 그리드를 생성해줍니다.
st = new StringTokenizer(br.readLine());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
arr = st.nextToken().toCharArray();
grid = new char[r][c]; // 입력받은 문자열을 저장하는 그리드
visit = new boolean[r][c]; // 소용돌이 패턴으로 읽기위한 방문여부
index = 0; // 그리드에 문자열을 넣기 위한 인덱스
// 문자열을 그리드에 저장
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (index < arr.length) {
grid[i][j] = arr[index];
index++;
} else {
grid[i][j] = '0';
}
}
}
index가 입력받은 문자열 arr의 길이보다 커지면 무조건 '0'이 들어가게 해주었습니다.
4-2. 계산에 필요한 변수들을 초기화 해줍니다.
s = ""; // 5자리이진수를 저장하는 문자열
str = ""; // 알파벳으로 변환된 문자열
dir = 0; // 0, 1, 2, 3 동서남북 위치 표시
y = 0; // 현재 참조하는 y좌표
x = 0; // 현재 참조하는 x좌표
4-3. 소용돌이 방향으로 이동을 위해 반복문을 통해 비밀메시지를 구합니다.
// 방문한 곳을 또 방문하면 소용돌이가 끝난 것
while (check(y, x, r, c)) {
s += grid[y][x]; // 이진수를 문자열에 저장
visit[y][x] = true; // 방문 표시
// 방향전환을 위한 체크
if (!check(y + dy[dir], x + dx[dir], r, c)) {
dir++;
if (dir == 4) {
dir = 0;
}
}
// 현재 방향으로 좌표 이동
y += dy[dir];
x += dx[dir];
// 5자리가 완성되면 알파벳 문자열 저장
if (s.length() == 5) {
str += map.get(s);
s = "";
}
}
// 방문 여부와 grid 범위 안인지 체크하는 메소드
private static boolean check (int y, int x, int r, int c) {
return 0 <= y && 0 <= x && y < r && x < c && !visit[y][x];
}
- grid에 저장된 이진수를 이진수를 저장하는 문자열에 저장합니다.
- 방향전환을 위해 그리드의 범위 안인지, 이미 방문을 했는지 체크하여 방향전환을 해줍니다.
- 현재 방향만큼 현재 위치를 이동합니다.
- 이진수를 저장한 문자열이 5자리가 된다면 map에 값을 넣어 대문자 알파벳 or 공백을 비밀메시지를 저장하는 문자열에 저장합니다.
5. 반복문이 종료되면 빈 공백을 제외한 문자열을 출력해줍니다.
// 뒷 빈 공백 제거 후 출력
str = spaceRemove(str);
sb.append(str).append("\n");
// 완성된 문자열 빈 공백 제거 메소드
private static String spaceRemove (String s) {
int index = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) != ' ') {
index = i;
break;
}
}
return s.substring(0, index + 1);
}
🟪 코드
package Main;
import java.io.*;
import java.util.*;
public class Main {
static boolean[][] visit;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringBuilder sb = new StringBuilder();
// A ~ Z까지의 모든 5자리이진수를 저장합니다.
Map<String, Character> map = new LinkedHashMap<>();
map.put("00000", ' ');
for (int i = 0; i < 26; i++) {
map.put(format(i + 1), (char)('A' + i));
}
// 계산에 필요한 변수를 선언
int r, c, dir, index, y, x;
String s, str;
char[] arr;
char[][] grid;
StringTokenizer st;
// 동서남북 이동을 위한 좌표 설정
int[] dx = {1, 0, -1, 0};
int[] dy = {0, 1, 0, -1};
// 테스트 케이스의 수
int t = Integer.parseInt(br.readLine());
// 테스트 케이스 수만큼 반복
while (t-- > 0) {
st = new StringTokenizer(br.readLine());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
arr = st.nextToken().toCharArray();
grid = new char[r][c]; // 입력받은 문자열을 저장하는 그리드
visit = new boolean[r][c]; // 소용돌이 패턴으로 읽기위한 방문여부
index = 0; // 그리드에 문자열을 넣기 위한 인덱스
// 문자열을 그리드에 저장
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (index < arr.length) {
grid[i][j] = arr[index];
index++;
} else {
grid[i][j] = '0';
}
}
}
s = ""; // 5자리이진수를 저장하는 문자열
str = ""; // 알파벳으로 변환된 문자열
dir = 0; // 0, 1, 2, 3 동서남북 위치 표시
y = 0; // 현재 참조하는 y좌표
x = 0; // 현재 참조하는 x좌표
// 방문한 곳을 또 방문하면 소용돌이가 끝난 것
while (check(y, x, r, c)) {
s += grid[y][x]; // 이진수를 문자열에 저장
visit[y][x] = true; // 방문 표시
// 방향전환을 위한 체크
if (!check(y + dy[dir], x + dx[dir], r, c)) {
dir++;
if (dir == 4) {
dir = 0;
}
}
// 현재 방향으로 좌표 이동
y += dy[dir];
x += dx[dir];
// 5자리가 완성되면 알파벳 문자열 저장
if (s.length() == 5) {
str += map.get(s);
s = "";
}
}
// 뒷 빈 공백 제거 후 출력
str = spaceRemove(str);
sb.append(str).append("\n");
}
bw.write(sb.toString());
bw.flush();
bw.close();
br.close();
}
// 숫자를 5자리이진수로 변환하는 메소드
private static String format (int num) {
return String.format("%05d", Integer.parseInt(Integer.toBinaryString(num)));
}
// 방문 여부와 grid 범위 안인지 체크하는 메소드
private static boolean check (int y, int x, int r, int c) {
return 0 <= y && 0 <= x && y < r && x < c && !visit[y][x];
}
// 완성된 문자열 빈 공백 제거 메소드
private static String spaceRemove (String s) {
int index = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) != ' ') {
index = i;
break;
}
}
return s.substring(0, index + 1);
}
}
728x90
반응형
'코딩테스트 일기 (BAEKJOON)' 카테고리의 다른 글
BEAKJOON / 백준 - JAVA 32685번 4-LSB (0) | 2024.11.24 |
---|---|
BEAKJOON / 백준 - JAVA 31825번 장기 (0) | 2024.11.23 |
BEAKJOON / 백준 - JAVA 32290번 MEX vs OR (0) | 2024.11.21 |
BEAKJOON / 백준 - JAVA 32371번 샷건 (0) | 2024.11.20 |
BEAKJOON / 백준 - JAVA 32215번 코드마스터 2024 (0) | 2024.11.19 |