https://www.acmicpc.net/problem/3055
3055번: 탈출
사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제
www.acmicpc.net
BFS의 응용 문제이다.
BFS
- queue에서 꺼내옴
- 목적지인가?
- 연결된 곳 순회
- 갈 수 있는가?
- 체크인
- queue에 넣음
- 체크아웃(잘 사용하지 x)
한 큐에 물과 고슴도치를 같이 넣어 고려한다.
다음 턴에 물이 찰 예정인 칸에 고슴도치가 갈 수 없기 때문에 물을 먼저 체크한다.
물의 방문 체크는 *인 곳을 그냥 물로 만들고
고슴도치의 방문 체크는 time이라는 이차원 배열을 map사이즈 만큼 할당해서 방문 시간을 표기한다.
한 큐에 넣기때문에 물로 방문할 곳인지 고슴도치로 방문할 곳인지 구분하기 위해서 다음턴에 퍼진 물의 수(큐에 넣을 때 센다), 고슴도치 방문 수를 기록한다.
class Point{
int r;
int c;
public Point(int r, int c){
this.r = r;
this.c = c;
}
}
public class Main {
static int R, C;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
Point S = null, D = null;
char[][] map = new char[R][C];
int[][] check = new int[R][C];
ArrayList<Point> water = new ArrayList<>();
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]=='S'){
S = new Point(i, j);
}
if(map[i][j]=='D'){
D = new Point(i, j);
}
if(map[i][j]=='*'){
water.add(new Point(i,j));
}
}
}
bfs(S, D, map, check, water);
}
// 1. 큐에서 꺼내옴
// 2. 목적지 : 비버굴 D
// 3. 연결된 곳 순회 : 일단 좌 우 위 아래가 다 가능하다고 생각
// 4. 갈 수 있는가? : 맵 영역을 넘어가는 지, 돌이나 물이 아닌지(.인데 물이 인접해있지 않은), 방문하지 않은 곳,
// 5. 체크인 (T/F) : 근데 time을 결과로 원하기 때문에 배열에 시간을 기록해 둠. 지도와 같은 사이즈의 int 배열을 하나 만들어 체크인 용도로 사용
// 6. 큐에 넣음
// 고슴도치 뿐만 아니라 물도 이동. 물은 고슴도치와 다르게 목적지가 없음. 연결된 곳을 모두 감.
// 갈 수 있는 곳 : 돌이 아닌 곳, 맵 영역 안, (.)
// 체크인은 맵에 그냥 *로
// 큐에 고슴도치 이동, 물 이동 같이
// 근데 큐에 물을 먼저 넣으면 다음 물이 들어올 . 을 따로 체크하지 않아도 됨
static void bfs(Point S, Point D, char[][] map, int[][] check, ArrayList<Point> water){
int[] mc = {-1, 1, 0, 0};
int[] mr = {0, 0, -1, 1};
Queue<Point> que = new LinkedList<>();
for(Point p:water) que.offer(p);
que.offer(S);
int time = 1;
check[S.r][S.c] = time;
int w = water.size();
int s = 1;
while(!que.isEmpty()){
int wt = w;
w = 0;
for(int k=0; k<wt; k++){
Point u = que.poll();
for(int i=0; i<4; i++){
if(u.r+mr[i]>=0 && u.r+mr[i]<R
&& u.c+mc[i]>=0 && u.c+mc[i]<C
&& map[u.r+mr[i]][u.c+mc[i]]=='.'){
map[u.r+mr[i]][u.c+mc[i]] = '*';
que.offer(new Point(u.r+mr[i], u.c+mc[i]));
w++;
}
}
}
time++;
int st = s;
s = 0;
for(int k=0; k<st; k++){
Point u = que.poll();
for(int i=0; i<4; i++){
if(u.r+mr[i]>=0 && u.r+mr[i]<R
&& u.c+mc[i]>=0 && u.c+mc[i]<C){
if(map[u.r+mr[i]][u.c+mc[i]]=='.' && check[u.r+mr[i]][u.c+mc[i]]==0){
check[u.r+mr[i]][u.c+mc[i]] = time;
que.offer(new Point(u.r+mr[i],u.c+mc[i]));
s++;
}
else if(map[u.r+mr[i]][u.c+mc[i]]=='D'){
System.out.println(time-1);
return;
}
else if(map[u.r+mr[i]][u.c+mc[i]]=='X') continue;
}
}
}
}
System.out.println("KAKTUS");
}
}
'알고리즘' 카테고리의 다른 글
[백준 - 1202] 보석 도둑 - Java (0) | 2022.02.07 |
---|---|
[백준 - 2096] 내려가기 - Java (0) | 2022.02.07 |
[백준 - 1806] 부분합 - Java (0) | 2022.02.07 |
[백준 - 1759] 암호 만들기 - Java (0) | 2022.02.07 |
2021 KAKAO BLIND RECURUITMENT 메뉴 리뉴얼 (0) | 2021.07.22 |