1. 문제 링크
https://www.acmicpc.net/problem/5427
5427번: 불
상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에
www.acmicpc.net
2. 나의 코드
메모리: 116604kb
시간: 924ms
코드 길이: 2228B
시간 복잡도 : O(RC)
설명
- 사람이 이동하는 경로와 불이 번지는 경로를 따로 큐로 처리
- 만약 더이상 사람이 이동할 경로가 없으면 Impossible 출력
- 만약 사람이 map의 가장자리에 도착하면 시간을 출력
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int[] dr = {-1, 1, 0, 0};
static int[] dc = {0, 0, -1, 1};
static int R, C;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = null;
int test = Integer.parseInt(br.readLine());
for (int t = 0; t < test; t++) {
Queue<Point> fires = new LinkedList<>();
Queue<Point> humans = new LinkedList<>();
int result = 0;
boolean possible = false;
st = new StringTokenizer(br.readLine());
C = Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());
char[][] map = new char[R][C];
for (int i = 0; i < R; i++) {
String s = br.readLine();
for (int j = 0; j < C; j++) {
map[i][j] = s.charAt(j);
if (map[i][j] == '*') fires.offer(new Point(i, j));
else if (map[i][j] == '@') humans.offer(new Point(i, j));
}
}
while (!possible && !humans.isEmpty()) {
result++;
// 불 번지기
for (int i = 0, size = fires.size(); i < size; i++) {
Point fireNow = fires.poll();
for (int d = 0; d < 4; d++) {
int nr = fireNow.x + dr[d];
int nc = fireNow.y + dc[d];
if (isValid(nr, nc) && map[nr][nc] != '#' && map[nr][nc] != '*') {
map[nr][nc] = '*';
fires.offer(new Point(nr, nc));
}
}
}
// 사람 이동
for (int i = 0, size = humans.size(); i < size; i++) {
Point humanNow = humans.poll();
if (humanNow.x == 0 || humanNow.x == R - 1 || humanNow.y == 0 || humanNow.y == C - 1) {
possible = true;
break;
}
for (int d = 0; d < 4; d++) {
int nr = humanNow.x + dr[d];
int nc = humanNow.y + dc[d];
if (isValid(nr, nc) && map[nr][nc] == '.') {
map[nr][nc] = '@';
humans.offer(new Point(nr, nc));
}
}
}
}
System.out.println((possible) ? result : "IMPOSSIBLE");
}
}
public static boolean isValid(int r, int c) {
return 0 <= r && r < R && 0 <= c && c < C;
}
}
3. 정답 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int w,h;
static char[][] map;
static Queue<int[]> person;
static Queue<int[]> fire;
static int[] dx = {-1,1,0,0};
static int[] dy = {0,0,-1,1};
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int tc = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
while(tc-->0) {
StringTokenizer st = new StringTokenizer(br.readLine());
w = Integer.parseInt(st.nextToken());
h = Integer.parseInt(st.nextToken());
map = new char[h][w];
fire = new LinkedList<>();
person = new LinkedList<>();
for(int i=0; i<h; i++) {
String line = br.readLine();
for(int j=0; j<w; j++) {
char c = line.charAt(j);
if(c=='@') {
person.add(new int[] {j,i,0});
}else if(c=='*') {
fire.add(new int[] {j,i});
}
map[i][j] = c;
}
}
int res= -1;
out : while(true) {
// 1. 불 번짐
int fSize = fire.size();
for(int i=0; i<fSize; i++) {
int[] pos = fire.poll();
int px = pos[0], py = pos[1];
fireMarking(px, py);
}
// 2. 상근 이동 (1번 불번짐 영향 x, 그러나 번질 곳으로 이동은 x)
int pSize = person.size();
for(int i=0; i<pSize; i++) {
int[] pos = person.poll();
int px = pos[0], py = pos[1], time =pos[2];
res = escape(px, py, time);
if(res != -1) {
break out;
}
}
if(person.isEmpty()) break;
}
if(res !=-1) sb.append(res+"\n");
else sb.append("IMPOSSIBLE\n");
}
System.out.println(sb.toString());
}
static int escape(int x, int y, int time) {
for(int i=0; i<4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if(nx<0 || nx>w-1 || ny<0 || ny>h-1) {
return time+1;
}
if(map[ny][nx] == '.') {
map[ny][nx] = '@';
person.add(new int[] {nx, ny, time+1});
}
}
return -1;
}
static void fireMarking(int x, int y) {
for(int i=0; i<4; i++) {
int nx = x+dx[i];
int ny = y+dy[i];
if(nx<0 || nx>w-1 || ny<0 || ny>h-1) continue;
// 빈공간 , 상근 위치
if(map[ny][nx] == '.' || map[ny][nx] == '@') {
map[ny][nx] = '*';
fire.add(new int[] {nx,ny});
}
}
}
}
4. 배운 점
- 만약 큐의 사이즈 만큼 돌려야 한다면 size를 선언한 후 하도록 하자
'Algorithm > Problem' 카테고리의 다른 글
불!(BJ_G3_4179) (0) | 2024.05.27 |
---|---|
인구 이동(BJ_G4_16234) (0) | 2024.04.22 |
치즈(BJ_G4_2636) (0) | 2024.04.13 |
파티 (BJ_G3_1238) (0) | 2024.04.08 |
0 만들기(BJ_G5_7490) (0) | 2024.04.07 |