https://www.acmicpc.net/problem/1987
문제 요약 :
1. R과 C 입력받기
2. R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들을 입력받기
3. 좌측 상단 칸(1행 1열)에는 말이 놓여 있다.
4. 말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다.
4-1. 즉, 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.
5. 말이 최대한 몇 칸 지날 수 있는지 구하는 프로그램 작성
5-1. 말이 지나는 칸은 좌측 상단의 칸도 포함
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
// 시도 3. 메모리 15200KB, 시간 856ms
public class Main {
private static int r, c, max;
private static char[][] map;
private static boolean[] check;
public static final int[][] DELTA = {{-1,0},{1,0},{0,-1},{0,1}}; // 상, 하, 좌, 우
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
// 1. R과 C 입력받기
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
map = new char[r][c];
// 2. R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들을 입력받기
for (int i = 0; i < r; i++) {
String line = br.readLine();
for (int j = 0; j < line.length(); j++) {
map[i][j] = line.charAt(j);
}
}
max = 0;
// 지나온 알파벳을 저장할 배열 생성, 좌측 상단 값을 true로 변경
check = new boolean[26];
// 3. 좌측 상단 칸(1행 1열)에는 말이 놓여 있다
check[map[0][0] - 'A'] = true;
// 5. 말이 최대한 몇 칸 지날 수 있는지 구하는 프로그램 작성
//5-1. 말이 지나는 칸은 좌측 상단의 칸도 포함
move(0,0, 1);
System.out.println(max);
}
// 4. 말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다.
private static void move(int x, int y, int cnt) {
if (cnt > max) max = cnt;
for (int[] delta : DELTA) {
int nr = x + delta[0];
int nc = y + delta[1];
// 범위 안에 해당
if (isRange(nr, nc)) {
// 사용하지 않은 알파벳이라면
if (!check[map[nr][nc] - 'A']) {
// true로 변경해주고 재귀 호출
check[map[nr][nc] - 'A'] = true;
move(nr, nc, cnt + 1);
// 원상복구
check[map[nr][nc] - 'A'] = false;
}
}
}
}
private static boolean isRange(int nr, int nc) {
return nr >= 0 && nr < r && nc >= 0 && nc < c;
}
}
더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
private static int r, c, max;
private static Character[][] map;
private static boolean[][] visited;
private static List<Character> check;
public static final int[][] DELTA = {{-1,0},{1,0},{0,-1},{0,1}}; // 상, 하, 좌, 우
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
map = new Character[r][c];
for (int i = 0; i < r; i++) {
String line = br.readLine();
for (int j = 0; j < line.length(); j++) {
map[i][j] = line.charAt(j);
}
}
max = 0;
visited = new boolean[r][c];
visited[0][0] = true;
check = new ArrayList<>();
check.add(map[0][0]);
move(0,0, 1);
System.out.println(max);
}
private static void move(int x, int y, int cnt) {
if (cnt > max) max = cnt;
for (int[] delta : DELTA) {
int nr = x + delta[0];
int nc = y + delta[1];
if (isRange(nr, nc)) {
if (!visited[nr][nc] && canMove(map[nr][nc])) {
visited[nr][nc] = true;
check.add(map[nr][nc]);
move(nr, nc, cnt + 1);
visited[nr][nc] = false;
check.remove(map[nr][nc]);
}
}
}
}
private static boolean canMove(Character c) {
return !check.contains(c);
}
private static boolean isRange(int nr, int nc) {
return nr >= 0 && nr < r && nc >= 0 && nc < c;
}
}
첫 번째 시도, 메모리 22276KB, 시간 4200ms
DFS를 사용해 풀었었다.
public class Main {
private static int r, c, max;
private static Character[][] map;
private static boolean[] check;
public static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final int[][] DELTA = {{-1,0},{1,0},{0,-1},{0,1}}; // 상, 하, 좌, 우
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
map = new Character[r][c];
for (int i = 0; i < r; i++) {
String line = br.readLine();
for (int j = 0; j < line.length(); j++) {
map[i][j] = line.charAt(j);
}
}
max = 0;
// 지나온 알파벳을 저장할 배열 생성, 좌측 상단 값을 true로 변경
check = new boolean[26];
check[ALPHABET.indexOf(map[0][0])] = true;
move(0,0, 1);
System.out.println(max);
}
private static void move(int x, int y, int cnt) {
if (cnt > max) max = cnt;
for (int[] delta : DELTA) {
int nr = x + delta[0];
int nc = y + delta[1];
// 범위 안에 해당
if (isRange(nr, nc)) {
// 사용하지 않은 알파벳이라면
if (!check[ALPHABET.indexOf(map[nr][nc])]) {
// true로 변경해주고 재귀 호출
check[ALPHABET.indexOf(map[nr][nc])] = true;
move(nr, nc, cnt + 1);
// 원상복구
check[ALPHABET.indexOf(map[nr][nc])] = false;
}
}
}
}
private static boolean isRange(int nr, int nc) {
return nr >= 0 && nr < r && nc >= 0 && nc < c;
}
}
두 번째 시도, 메모리 16388KB, 시간 2572ms
ArrayList의 contains로 확인하던 로직을 indexOf로 변경
'알고리즘' 카테고리의 다른 글
[백준] | JAVA, 자바 | 10026번 - 적록색약 (0) | 2025.03.09 |
---|---|
[백준] | JAVA, 자바 | 2636번 - 치즈 (0) | 2025.03.08 |
[백준] | JAVA, 자바 | 14940번 - 쉬운 최단거리 (0) | 2025.03.04 |
[백준] | JAVA, 자바 | 1697번 - 숨바꼭질 (0) | 2025.02.12 |
[백준] | JAVA, 자바 | 2178번 - 미로 탐색 (0) | 2025.02.11 |