백준_말이 되고픈 원숭이_1600[Java]

2019. 4. 22. 17:50알고리즘문제/백준

문제

https://www.acmicpc.net/problem/1600

 

1600번: 말이 되고픈 원숭이

첫째 줄에 자연수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있는 곳으로는 이동할 수 없다. 시작점과 도착점은 항상 평지이다. W와 H는 1이상 200이하의 자연수이고, K는 0이상 30이하의 정수이다.

www.acmicpc.net

 

풀이

BFSK가 남았는지 확인해가면서 인접한 칸으로 이동하거나 말처럼 이동하는 경우를 탐색하여 

가장 먼저 목표지점에 도달했을 때의 이동 횟수를 출력한다. 

 

Queue에는 현재 위치 정보(x,y)와 해당 위치에 오기 위해 이동한 횟수(cnt), 그리고 남은 K의 갯수(k)를 담는다. 

 

* 문제점

목표지점에 도달하는 하나의 경로에서 이미 방문한 위치에 재방문하지 않기 위해 방문 기록을 저장하는 2차원 배열(visit)을 선언하였다.

하지만 BFS방식이었기 때문에 탐색하고 있는 현재 경로가 아닌 다른 경로에서 먼저 방문했을 때 현재 경로에서 해당 위치를 방문하지 못하는 문제점이 발생하였다. (다른 경로가 서로의 탐색에 관여하게 됨) 따라서 백준의 질문탭에서 나와 같은 문제에 부딪힌 사람이 있었고 그 덕분에 문제를 해결할 수 있었다. 링크

 

-> 해결방법 

visit3차원 배열로 선언한다. 

 

 

아래 두가지 테스트케이스를 만족하면 된다.. !

 

- TEST CASE 01

INPUT : 

4

6 10

0 0 1 1 1 1

0 1 1 0 1 1

0 1 1 1 1 0

0 1 1 1 1 0

0 1 1 1 1 0

0 1 1 1 1 0

0 1 1 0 1 1

0 1 1 1 1 1

1 1 1 1 0 0

1 0 0 1 1 0

OUTPUT : 10 

 

- TEST CASE 02

INPUT : 

1

4 4

0 1 1 1

0 0 1 1

1 0 1 1

1 1 1 0

OUTPUT : 4

 

코드

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
	static int K, W, H;
	static int[][] map;
	static boolean[][][] visit;

	static class Pair{
		int x;
		int y;
		int cnt;
		int k;
		
		Pair(int x, int y, int cnt, int k){
			this.x = x;
			this.y = y;
			this.cnt = cnt;
			this.k = k;
		}
	}
    
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		K = sc.nextInt();
		W = sc.nextInt();
		H = sc.nextInt();
		
		map = new int[H][W];
		visit = new boolean[H][W][31];
		for(int i = 0; i < H; i++) {
			for(int j = 0; j < W; j++) {
				map[i][j] = sc.nextInt();
			}
		}

		visit[0][0][0] = true;
		solution();
		
		sc.close();
	}

	// 동서남북 좌우상하(말)
	static int[] dx = {1,-1, 0, 0};
	static int[] dy = {0, 0, 1, -1}; 
	static int[] hx = {-2, -2, 2, 2, 1, -1, 1, -1};
	static int[] hy = {1, -1, 1, -1, 2, 2, -2, -2};
	private static void solution() {
		Queue<Pair> q = new LinkedList<Pair>();
		q.add(new Pair(0,0,0,K));
		
		while(!q.isEmpty()) {
			Pair cur = q.poll();
			int curX = cur.x;
			int curY = cur.y;
			int cnt = cur.cnt;
			int curK = cur.k;
			
			if(curX == W-1 && curY == H-1) {
				System.out.println(cnt);
				return;
			}
			
			if(curX >= W || curY >= H || curX < 0 || curY < 0) continue;
			if(map[curY][curX] == 1) continue;
			
			if(visit[curY][curX][curK]) continue;
			visit[curY][curX][curK] = true;
			
			for(int i = 0; i < 4; i++) {
				int nextX = curX + dx[i];
				int nextY = curY + dy[i];
				
				q.add(new Pair(nextX, nextY, cnt+1,  curK));
				
			}
			
			if(curK == 0) continue;
			for(int i = 0; i < 8; i++) {
				int nextX = curX + hx[i];
				int nextY = curY + hy[i];
				
				q.add(new Pair(nextX, nextY, cnt+1, curK-1));
				
			}
				
			
		}
		System.out.println("-1");
		return;
		
	}

}

 

참고

- 조건문 정리 어렵다아. 심플하게 작성하심 !

https://debuglog.tistory.com/90

 

백준 1600번 - 말이 되고픈 원숭이

백준 1600번 - 말이 되고픈 원숭이 https://www.acmicpc.net/problem/1600 문제 동물원에서 막 탈출한 원숭이 한 마리가 세상구경을 하고 있다. 그 녀석은 말(Horse)이 되기를 간절히 원했다. 그래서 그는 말의 움..

debuglog.tistory.com

 

- 반례 및 visit[] 배열을 3차원으로 선언해야하는 이유

https://www.acmicpc.net/board/view/30139

 

글 읽기 - 왜 틀렸는지 모르겠어요

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

'알고리즘문제 > 백준' 카테고리의 다른 글

백준_로봇 조종하기_2169[Java]  (0) 2019.04.24
백준_포도주마시기_2156[Java]  (0) 2019.04.24
백준_통나무 옮기기_1938[Java]  (0) 2019.04.19
백준_안전영역_2468[Java]  (0) 2019.04.19
백준_로봇_1726[Java]  (0) 2019.04.19