문제
출처 : https://www.acmicpc.net/problem/9944
N*M크기의 보드에 장애물(*) 빈칸(.)이 있다
보드의 빈칸위에 놓인 공은 다음 규칙에따라 움직인다.
- 위, 아래, 오른쪽, 왼쪽 중 방향 하나를 고른 다음, 그 방향으로 공을 계속해서 이동시킨다.
- 공은 장애물, 보드의 경계, 이미 공이 지나갔던 칸을 만나기 전까지 계속해서 이동한다.
게임은 공이 더 이상 이동할 수 없을때 끝난다.
모든 빈칸을 방문하기위한 이동횟수의 최솟값을 구하는 문제다.
(모든 빈칸을 방문하지 못한다면 -1 출력)
풀이
백트래킹 구현 문제다.
N,M이 30이라서 문제에서 시키는대로 구현하면 풀린다.
단, 공이 어느 위치에서든 시작할수있으므로, N*M그리드의 모든 빈칸에서 시작시켜야함에 주의하자.
백트래킹 소스코드
private int move(Pos pos, int cnt, int moveNum){
if(pos.y < 0 || pos.y >= N || pos.x < 0 || pos.x >= M) return 987654321;
if(cnt == this.cnt || moveNum >= ans) return moveNum;
int ret = ans;
int headY = pos.y+dy[pos.dir];
int headX = pos.x+dx[pos.dir];
if(headY < 0 || headY >= N || headX < 0 || headX >= M || check[headY][headX] || arr[headY][headX] == '*'){
for(int i = 0; i < 4; i++){
if(pos.dir == i) continue;
int nextY = pos.y + dy[i];
int nextX = pos.x + dx[i];
int nextMoveNum = moveNum+1;
if(nextY < 0 || nextY >= N || nextX < 0 || nextX >= M || check[nextY][nextX] || arr[nextY][nextX] == '*')
continue;
check[nextY][nextX] = true;
ret = Math.min(ret, move(new Pos(nextY, nextX, i), cnt+1, nextMoveNum));
check[nextY][nextX] = false;
}
}
else if(headY >= 0 && headY < N && headX >= 0 && headX < M ){
check[headY][headX] = true;
ret = Math.min(ret, move(new Pos(headY, headX, pos.dir), cnt+1, moveNum));
check[headY][headX] = false;
}
return ret;
}
EOF처리를 상당히 오랫동안 했는데, 이상하게 내 컴파일 환경에서는 null일경우 종료처리를 해줘도 NumberFormatException을 뿜으며 종료되었다.. 몇번해보다 안되서 그대로 제출했더니 백준에서는 AC가 나옴
(다른사람 AC코드를 가져와서 내 컴파일러에서 돌려봐도 이상한 예외를 뿜으며 종료된다.)
소스코드
'알고리즘 (2020 : 08 : 10 ~ ) > 구현, 시뮬' 카테고리의 다른 글
[백준 / BOJ] 20920 영단어 암기는 괴로워 (0) | 2021.07.13 |
---|---|
[백준 / BOJ] 8972 미친 아두이노 (0) | 2021.07.12 |
[백준 / BOJ] 18500 미네랄 2 (Java) / 2933 미네랄 1 포함 (0) | 2021.05.10 |
[백준 / BOJ] 17780 새로운 게임 (Java) (0) | 2021.05.09 |
[백준 / BOJ] 1938 통나무 옮기기 (0) | 2021.04.27 |