-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[김채은] 3주차 과제 제출합니다 #15
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
https://www.acmicpc.net/problem/3055 | ||
|
||
![](https://velog.velcdn.com/images/chaen-ing/post/ffbb6f17-ff8a-47bb-b8fd-31aaae46096d/image.png) | ||
|
||
첫째 줄에 50보다 작거나 같은 자연수 R과 C가 주어진다. | ||
|
||
R개 줄에는 티떱숲의 지도가 주어지며, 문제에서 설명한 문자만 주어진다. 'D'와 'S'는 하나씩만 주어진다. | ||
|
||
첫째 줄에 고슴도치가 비버의 굴로 이동할 수 있는 가장 빠른 시간을 출력한다. 만약, 안전하게 비버의 굴로 이동할 수 없다면, "KAKTUS"를 출력한다. | ||
|
||
#### 🔎 문제 정리 | ||
**R행 C열**의 지도 존재 | ||
- **고슴도치 (S)** | ||
- 비버의 위치(D)까지 _최소 이동 횟수_로 이동해야함 | ||
- 물과 돌 통과 불가 | ||
- 물이 찰 예정인 칸으로도 이동 불가 | ||
- 상하좌우로 이동 | ||
- ** 물 (*)** | ||
- 돌 통과 불가 | ||
- 비버의 위치로 확장 불가 | ||
- 상하좌우로 확장 | ||
- **빈곳 (.)** | ||
- **돌 (x)** | ||
|
||
|
||
#### 🔎 문제 해결 순서 | ||
|
||
1. 고슴도치의 위치, 현재 맵 등 입력 정보를 받아준다 | ||
|
||
2. `bfs()` & `flood()` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bfs() & flood() 의 의미가 무엇인지 여쭤봐도 될까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 둘다 메서드인데 설명이 부족했던 것 같네요!! 추후에 블로그에 더 추가해놓겠습니다. 간단하게 말씀드리자면 flood는 이동전에 물이 차오를 곳을 미리 체크하는 로직, bfs는 flood의 결과를 바탕으로 이동할 수 있는 곳을 체크하는 로직이라고 보시면 될 것 같습니다. 리뷰감사합니다~👍 |
||
|
||
3. 먼저 `bfs()`에서 `flood()` 호출 | ||
|
||
물이 차오를 예정인 곳에 고슴도치가 방문 불가능 하므로 먼저 물이 차오를 곳을 검토해준다. | ||
check 배열에 못가는 곳은 -1로 체크 | ||
- 동서남북으로 물 흐르도록 | ||
- 이미 방문했거나 돌이 있는 곳으로는 X | ||
- 종료 노드로는 물이 흐를 수 X | ||
|
||
4. 다시 `bfs()`로 | ||
|
||
> 이때 **BFS**란? | ||
**Breadth-First Search** | ||
그래프에서 탐색을 할때 깊게 탐색하는 것이 아니라 넓게 탐색하는 방법이다. | ||
반대로 DFS는 깊게 그래프를 탐색하는 방식이다. | ||
|
||
BFS이므로 Queue를 사용한다. | ||
반복문을 돌면서 check 배열에 이동횟수를 넣어준다. | ||
- 돌 or 물 있는곳 X | ||
- 이미 갔던곳 X | ||
- → 즉 0인 곳만 갈 수 있음 | ||
5. 종료노드에 도달못하면 false, 도달하면 true를 메인으로 넘겨준다 | ||
- false : KAKTUS 출력 | ||
- true : 이동 횟수를 출력 | ||
|
||
#### 🔎 코드 | ||
|
||
```java | ||
package boj3055; | ||
|
||
import java.io.*; | ||
import java.util.*; | ||
|
||
public class Main { | ||
static char[][] map; | ||
static int[][] check; | ||
static int[] DX = {1,-1,0,0}; | ||
static int[] DY = {0,0,1,-1}; | ||
static Queue<Node> water; | ||
static Node endNode; | ||
|
||
public static void main(String[] args) throws IOException { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
|
||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
int R = Integer.parseInt(st.nextToken()); | ||
int C = Integer.parseInt(st.nextToken()); | ||
|
||
map = new char[R][C]; | ||
check = new int[R][C]; | ||
|
||
Node startNode = new Node(0,0); // 고슴도치 위치 | ||
water = new LinkedList<>(); | ||
|
||
// map 입력받기 | ||
for(int i = 0; i < R; i++){ | ||
String line = br.readLine(); | ||
for(int j = 0; j < C; j++){ | ||
map[i][j] = line.charAt(j); | ||
if (line.charAt(j)== 'S'){ // 시작 | ||
startNode = new Node(i,j); | ||
}else if(line.charAt(j) == '*'){ // 물 | ||
check[i][j] = -1; | ||
water.offer(new Node(i,j)); | ||
}else if(line.charAt(j) == 'X'){ // 돌 | ||
check[i][j] = -1; | ||
}else if(line.charAt(j) == 'D'){ // 종료 | ||
endNode = new Node(i,j); | ||
} | ||
} | ||
} | ||
|
||
boolean flag = bfs(R,C,startNode); | ||
if(!flag) System.out.println("KAKTUS"); | ||
else System.out.println(check[endNode.x][endNode.y]); | ||
} | ||
|
||
static boolean bfs(int r, int c, Node startNode){ | ||
Queue<Node> queue = new LinkedList<>(); | ||
queue.offer(startNode); | ||
|
||
int time = 0; | ||
|
||
while(!queue.isEmpty()) { | ||
time++; | ||
flood(r,c); // 물 흐름 | ||
|
||
int size = queue.size(); | ||
while(size-->0) { // 현재 큐에 있는 횟수만큼 반복 | ||
Node node = queue.poll(); | ||
int minTime = check[node.x][node.y]; | ||
|
||
for (int i = 0; i < 4; i++) { | ||
int dx = node.x + DX[i]; | ||
int dy = node.y + DY[i]; | ||
|
||
if (dx < 0 || dx >= r || dy < 0 || dy >= c) { // 범위 | ||
continue; | ||
} else if (check[dx][dy] == 0) { | ||
check[dx][dy] = time; | ||
queue.offer(new Node(dx, dy)); | ||
} | ||
|
||
if (dx == endNode.x && dy == endNode.y) // 종료노드 도달시 끝 | ||
return true; | ||
|
||
|
||
} | ||
} | ||
|
||
|
||
} | ||
return false; // 종료노드에 도달 불가 | ||
} | ||
|
||
static void flood(int r, int c) { | ||
int size = water.size(); | ||
|
||
for (int i = 0; i < size; i++) { | ||
Node node = water.poll(); | ||
|
||
for (int j = 0; j < 4; j++) { | ||
int dx = node.x + DX[j]; | ||
int dy = node.y + DY[j]; | ||
|
||
if (dx < 0 || dx >= r || dy < 0 || dy >= c) { // 범위 초과 | ||
continue; | ||
} else if (check[dx][dy] == -1) { // 이미 방문 or 돌 | ||
continue; | ||
} else if (dx == endNode.x && dy == endNode.y) { | ||
continue; | ||
} else { | ||
check[dx][dy] = -1; | ||
water.offer(new Node(dx, dy)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
class Node{ | ||
int x, y; | ||
|
||
public Node(int x, int y) { | ||
this.x = x; | ||
this.y = y; | ||
} | ||
} | ||
|
||
|
||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
문제를 요약해서 정리해주신 덕분에 문제를 파악하기 수월했습니다.