https://www.acmicpc.net/problem/3055
문제 요약 :
1. 50보다 작거나 같은 자연수 R과 C가 주어진다.
2. R개 줄에는 티떱숲의 지도가 주어지며, 문제에서 설명한 문자만 주어진다. 'D'와 'S'는 하나씩만 주어진다.
2-1. 티떱숲의 지도는 R행 C열로 이루어져 있다. 비어있는 곳은 '.'로 표시되어 있고, 물이 차있는 지역은 '*', 돌은 'X'로 표시되어 있다. 비버의 굴은 'D'로, 고슴도치의 위치는 'S'로 나타내어져 있다.
3. 매 분마다 고슴도치는 현재 있는 칸과 인접한 네 칸 중 하나로 이동할 수 있다. (위, 아래, 오른쪽, 왼쪽)
4. 물도 매 분마다 비어있는 칸으로 확장한다. 물이 있는 칸과 인접해 있는 비어있는 칸(적어도 한 변을 공유)은 물이 차게 된다.
5. 물과 고슴도치는 돌을 통과할 수 없다. 또, 고슴도치는 물로 차있는 구역으로 이동할 수 없고, 물도 비버의 소굴로 이동할 수 없다.
5-1. 고슴도치는 물이 찰 예정인 칸으로 이동할 수 없다. 즉, 다음 시간에 물이 찰 예정인 칸으로 고슴도치는 이동할 수 없다. 이동할 수 있으면 고슴도치가 물에 빠지기 때문이다.
6. 티떱숲의 지도가 주어졌을 때, 고슴도치가 안전하게 비버의 굴로 이동하기 위해 필요한 최소 시간을 구하는 프로그램을 작성하시오.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static class Coordinate {
int x;
int y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
}
private static int R, C;
private static char[][] map;
private static Queue<Coordinate> waterQueue;
private static Coordinate hedgehog;
private static 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. 50보다 작거나 같은 자연수 R과 C가 주어진다.
R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
map = new char[R][C];
waterQueue = new ArrayDeque<>();
// 2. R개 줄에는 티떱숲의 지도가 주어지며, 문제에서 설명한 문자만 주어진다. 'D'와 'S'는 하나씩만 주어진다.
for (int i = 0; i < R; i++) {
String line = br.readLine();
for (int j = 0; j < C; j++) {
char c = line.charAt(j);
if (c == '*') waterQueue.add(new Coordinate(i, j));
if (c == 'S') {
hedgehog = new Coordinate(i, j);
c = '.';
}
map[i][j] = c;
}
}
int cnt = move();
// 6. 비버의 굴로 이동하기 위해 필요한 최소 시간 출력
if (cnt == -1) {
System.out.println("KAKTUS");
} else {
System.out.println(cnt);
}
}
// 4. 물도 매 분마다 비어있는 칸으로 확장한다. 물이 있는 칸과 인접해 있는 비어있는 칸(적어도 한 변을 공유)은 물이 차게 된다.
private static void expansionWater() {
int size = waterQueue.size();
Queue<Coordinate> nextQueue = new ArrayDeque<>();
for (int i = 0; i < size; i++) {
Coordinate temp = waterQueue.poll();
for (int j = 0; j < 4; j++) {
int nr = temp.x + delta[j][0];
int nc = temp.y + delta[j][1];
if (isRange(nr, nc) && map[nr][nc] == '.') {
map[nr][nc] = '*';
nextQueue.add(new Coordinate(nr, nc));
}
}
}
waterQueue.addAll(nextQueue);
}
// 3. 매 분마다 고슴도치는 현재 있는 칸과 인접한 네 칸 중 하나로 이동할 수 있다. (위, 아래, 오른쪽, 왼쪽)
private static int move() {
Queue<Coordinate> moveList = new ArrayDeque<>();
moveList.add(hedgehog);
boolean[][] visited = new boolean[R][C];
visited[hedgehog.x][hedgehog.y] = true;
int cnt = 0;
while (!moveList.isEmpty()) {
int size = moveList.size();
expansionWater();
for (int i = 0; i < size; i++) {
Coordinate temp = moveList.poll();
if (map[temp.x][temp.y] == 'D') return cnt;
for (int j = 0; j < 4; j++) {
int nr = temp.x + delta[j][0];
int nc = temp.y + delta[j][1];
if (!isRange(nr, nc) || visited[nr][nc]) continue;
// 5. 물과 고슴도치는 돌을 통과할 수 없다. 또, 고슴도치는 물로 차있는 구역으로 이동할 수 없다.
if (map[nr][nc] == 'X' || map[nr][nc] == '*') continue;
if (map[nr][nc] == 'D') return cnt + 1;
visited[nr][nc] = true;
moveList.add(new Coordinate(nr, nc));
}
}
cnt++;
}
return -1;
}
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.StringTokenizer;
public class Main {
private static int R, C, MIN;
private static char[][] map;
private static int[][] delta = {{-1,0},{1,0},{0,-1},{0,1}}; // 상, 하, 좌, 우
private static boolean[][] visited, waterVisited;
static class Hedgehog{
int x;
int y;
public Hedgehog(int x, int y) {
this.x = x;
this.y = y;
}
}
private static Hedgehog hedgehog;
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 char[R][C];
visited = new boolean[R][C];
MIN = Integer.MAX_VALUE;
for (int i = 0; i < R; i++) {
String line = br.readLine();
for (int j = 0; j < C; j++) {
char c = line.charAt(j);
if (c == 'S') {
hedgehog = new Hedgehog(i, j);
c = '.';
}
map[i][j] = c;
}
}
visited[hedgehog.x][hedgehog.y] = true;
hedgehogMove(hedgehog.x, hedgehog.y, 0);
if (MIN == Integer.MAX_VALUE) {
System.out.println("KAKTUS");
} else {
System.out.println(MIN);
}
}
private static void searchWater () {
waterVisited = new boolean[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (map[i][j] == '*' && !waterVisited[i][j]) {
waterVisited[i][j] = true;
expansionWater(i,j);
}
}
}
}
private static void expansionWater(int x, int y) {
for (int i = 0; i < 4; i++) {
int nr = x + delta[i][0];
int nc = y + delta[i][1];
if (isRange(nr, nc) && !waterVisited[nr][nc] && map[nr][nc] == '.') {
waterVisited[nr][nc] = true;
map[nr][nc] = '*';
}
}
}
private static void hedgehogMove(int x, int y, int cnt) {
if (map[x][y] == 'X' || map[x][y] == '*') return;
if (cnt > MIN) return;
if (map[x][y] == 'D') {
if (MIN > cnt) MIN = cnt;
return;
}
for (int i = 0; i < 4; i++) {
int nr = x + delta[i][0];
int nc = y + delta[i][1];
if (isRange(nr, nc) && !visited[nr][nc]) {
visited[nr][nc] = true;
hedgehog.x = nr;
hedgehog.y = nc;
char[][] temp = new char[R][C];
for (int n = 0; n < R; n++) {
for (int m = 0; m < C; m++) {
temp[n][m] = map[n][m];
}
}
searchWater();
hedgehogMove(nr, nc, cnt + 1);
visited[nr][nc] = false;
hedgehog.x = x;
hedgehog.y = y;
for (int n = 0; n < R; n++) {
System.arraycopy(temp[n], 0, map[n], 0, C);
}
}
}
}
private static boolean isRange(int nr, int nc) {
return nr >= 0 && nr < R && nc >= 0 && nc < C;
}
}
처음 풀었던 코드, BFS가 아니라 DFS방식으로 풀기도 했고 맵을 복사하는 과정에서 메모리를 많이 사용해 메모리 초과가 나왔었다.
'알고리즘' 카테고리의 다른 글
[백준] | JAVA, 자바 | 1600번 - 말이 되고픈 원숭이 (0) | 2025.03.15 |
---|---|
[백준] | JAVA, 자바 | 4179번 - 불! (0) | 2025.03.14 |
[백준] | JAVA, 자바 | 1759번 - 암호 만들기 (0) | 2025.03.12 |
[백준] | JAVA, 자바 | 1189번 - 컴백홈 (0) | 2025.03.11 |
[백준] | JAVA, 자바 | 10026번 - 적록색약 (0) | 2025.03.09 |