문제
N×M크기의 배열로 표현되는 미로가 있다.
1 | 0 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | 1 | 1 |
미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오.
위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.
입력
첫째 줄에 두 정수 N, M(2≤N, M≤100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
출력
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
예제 입력
4 6
101111
101010
101011
111011
예제 출력
15
[코드]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import java.util.Scanner; public class Main { public static int N, M; public static int min = 1000000000; public static int dx[] = { 0, 0, 1, -1 }; public static int dy[] = { 1, -1, 0, 0 }; public static int[][] maze, visited, minValue; public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc = new Scanner(System.in); N = sc.nextInt(); M = sc.nextInt(); maze = new int[N][M]; visited = new int[N][M]; // 방문 여부 minValue = new int[N][M]; // 최단거리 String[] temp = new String[N]; for (int i = 0; i < N; i++) { temp[i] = sc.next(); } for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (temp[i].charAt(j) == '1') maze[i][j] = 1; } } visited[0][0] = 1; minValue[0][0] = 1; searchMin(0, 1); // -> searchMin(1, 0); // 밑으로 System.out.println(minValue[N - 1][M - 1]); } public static void searchMin(int x, int y) { if (maze[x][y] == 1) { visited[x][y] = 1; // 나 자신은 방문 했음! int min = 10000000; for (int i = 0; i < 4; i++) { if (x + dx[i] >= 0 && x + dx[i] < N && y + dy[i] >= 0 && y + dy[i] < M) { if (visited[x + dx[i]][y + dy[i]] == 1) { // 방문한 이전값들 중 최소값을 찾는 작업 min = Min(min, minValue[x + dx[i]][y + dy[i]]); } } } minValue[x][y] = min + 1; // 이전 값들중 최소값과 자기자신 더하기 if (x == N - 1 && y == M - 1) return; // 마지막 칸 도달하면 return for (int i = 0; i < 4; i++) { if (x + dx[i] >= 0 && x + dx[i] < N && y + dy[i] >= 0 && y + dy[i] < M) { // 옆으로 이동가능한가? if (visited[x + dx[i]][y + dy[i]] == 0 && maze[x + dx[i]][y + dy[i]] == 1) { // 아직 방문안했으며, 방문 할 수 있는 곳인가? searchMin(x + dx[i], y + dy[i]); } } } } } public static int Min(int a, int b) { return a < b ? a : b; } } | cs |
[알고리즘]
많은 사람들이 BFS 라서 큐에 푼 것 같은데
나는 사실 어떤 방식으로 푼건지 잘 모르겠다... 굳이 말하자면 약간 다이나믹 프로그래밍 같은 느낌인가?
체계가 좀 있어야하는데ㅜㅜ 맨날 이렇게 그냥 푸넹
searchMin 이라는 함수가 하는 일은
1. 맨 먼저 자기보다 위, 아래, 오른쪽, 왼쪽에 있는 칸 중 방문된 칸이 있다면 그 칸의 숫자들을 비교해 최솟값을 찾아낸다.
2. 그 최소값에 자기 수 1을 더해 minValue 배열의 자기자신의 칸에 저장한다.
3. 그리고, 방문되지 않은 자기 주변의 칸을 찾아 그곳으로 이동한다.
중간중간 갈 수 있는지를 확인해줄 수 있는 조건들 (if 문 안에 있는..) 이 너무 지저분해서 함수로 만들려고했는데,
스택오버플로우가 나서... 그대로 뒀다
너무 많이 호출되서 그런거같다..ㅎㅎ
'공부 > 알고리즘' 카테고리의 다른 글
백준5014_스타트링크 (1) | 2016.12.27 |
---|---|
백준1978_소수찾기 (2) | 2016.12.21 |
백준1094_막대기 (0) | 2016.11.29 |
백준1389_케빈 베이컨의 6단계 법칙 (0) | 2016.11.23 |
백준1149_RGB거리 (0) | 2016.11.21 |
댓글