[BOJ] 9944. NxM 보드 완주하기
Problem
제출일 : 2020-02-13
문제 풀이 시간 : 1H 30M
난이도 : ★★★☆
N×M 보드 위에서 할 수 있는 게임이 있다. 보드는 크기가 1×1인 정사각형 칸으로 나누어져 있다. 보드의 각 칸은 빈 칸 또는 장애물이다. 장애물은 아래 그림에선 어두운 사각형으로 표시되어져 있다.
게임을 시작하려면 보드의 빈 칸 위에 공을 하나 놓아야 한다. 아래 그림에서 공은 회색 점으로 표시되어져 있다. 게임은 단계로 이루어져 있고, 각 단계는 아래와 같이 구성되어져 있다.
- 위, 아래, 오른쪽, 왼쪽 중 방향 하나를 고른 다음, 그 방향으로 공을 계속해서 이동시킨다.
- 공은 장애물, 보드의 경계, 이미 공이 지나갔던 칸을 만나기 전까지 계속해서 이동한다.
게임은 공이 더 이상 이동할 수 없을 때 끝난다. 이 때, 모든 빈 칸을 공이 방문한 적이 있어야 한다.
아래 그림은 총 10단계 만에 모든 칸을 방문하는 방법이다.
보드의 상태가 주어졌을 때, 모든 칸을 방문하기 위한 이동 횟수의 최솟값을 구하는 프로그램을 작성하시오.
Input
입력은 여러 개의 테스트 케이스로 이루어져 있다.
각 테스트 케이스의 첫째 줄에는 보드의 크기를 나타내는 N과 M이 주어진다. N은 세로 크기, M은 가로 크기이고, 두 값은 30보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 상태가 주어진다. 보드의 상태는 장애물을 나타내는 '*'과 빈 칸을 나타내는 '.'으로 이루어져 있다.
입력으로 주어진 보드가 장애물로만 이루어진 경우는 없다.
Output
각 테스트 케이스마다 보드의 모든 빈 칸을 방문하는 최소 이동 횟수를 출력한다. 출력 형식은 예제를 참고한다.
만약, 모든 빈 칸을 방문할 수 없다면 최소 이동 횟수는 -1이다.
Example
input
5 5
**...
.....
....*
..*..
.....
3 4
****
*...
*..*
output
Case 1: 10
Case 2: 3
Solution & Inpression
색다른 DFS문제 + 입력의 개수가 정해지지 않았기 때문에 EOF 처리로 종료
출력 부분 대소문자와 띄어쓰기를 유의하여야 한다. >> 이부분을 찾느라 1시간이 넘게 걸림.....
Code
언어 : JAVA
메모리 : 20,148 kb
실행시간 : 356 ms
import java.util.Scanner;
public class Main {
static int N, M, ans;
static int[][] map;
// 상 하 좌 우
static int[] dr = { -1, 1, 0, 0 };
static int[] dc = { 0, 0, -1, 1 };
public static void main(String[] args) throws Exception {
//System.setIn(new FileInputStream("res/input.txt"));
Scanner sc = new Scanner(System.in);
int TC = 0;
while (sc.hasNext()) {
N = sc.nextInt();
M = sc.nextInt();
map = new int[N][M];
int blank = -1; // 빈 칸의 개수
for (int i = 0; i < N; i++) {
String str = sc.next();
for (int j = 0; j < M; j++) {
if (str.charAt(j) == '*')
map[i][j] = 1;
else {
map[i][j] = 0;
blank++;
}
}
}
ans = 123456789;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (map[i][j] == 0) {
map[i][j] = 1;
DFS(i, j, 0, blank);
map[i][j] = 0;
}
}
}
if (ans == 123456789)
ans = -1;
System.out.println("Case " + ++TC + ": " + ans);
}
}
private static void DFS(int i, int j, int cnt, int blank) {
if (blank == 0 && ans > cnt) {
ans = cnt;
return;
}
for (int dir = 0; dir < 4; dir++) {
int nr = i + dr[dir];
int nc = j + dc[dir];
if (isRange(nr, nc) && map[nr][nc] == 0) {
while (isRange(nr, nc) && map[nr][nc] == 0) {
map[nr][nc] = 1;
blank--;
nr += dr[dir];
nc += dc[dir];
}
nr -= dr[dir];
nc -= dc[dir];
DFS(nr, nc, cnt + 1, blank);
while (nr != i || nc != j) {
map[nr][nc] = 0;
blank++;
nr -= dr[dir];
nc -= dc[dir];
}
}
}
}
private static boolean isRange(int nr, int nc) {
if (0 <= nr && nr < N && 0 <= nc && nc < M)
return true;
return false;
}
}
'Problem > BOJ' 카테고리의 다른 글
[BOJ] 4963. 섬의 개수 - DFS (0) | 2020.02.14 |
---|---|
[BOJ] 1107. 리모컨 - BF (0) | 2020.02.14 |
[BOJ] 16985. Maaaaaaaaaze - Graph/BF/BFS (0) | 2020.02.12 |
[BOJ] 14501. 퇴사/15486. 퇴사2 - BF/DP (0) | 2020.02.06 |
[BOJ] 13023. ABCDE - Graph (2) | 2020.02.03 |