https://www.acmicpc.net/problem/14503
풀이
1. 현재 위치에서 왼쪽으로 90도씩 회전하면서 해당 방향으로 이동할 수 있다면 이동한다.
2. 이동한 위치에서 또 왼쪽으로 90도씩 회전하면서 해당 방향으로 이동할 수 있다면 이동한다.
3. 만일 모든 방향으로 이동할 수 없을 경우, 현재 위치에서 1칸 뒤 (현재 방향에서 반대 방향)가 빈 칸이면 (청소를 이미 했더라도) 현재 방향을 유지한 채 이동하고, 1칸 뒤가 벽이라면 작동을 멈춘다.
현재 위치에서 조건 따지고, 이동하고서도 똑같이 조건 따지고... 하는 과정이 계속 진행되는 형태라 재귀로 접근했다.
입력을 받고 여러 변수를 초기화하고 재귀 메서드를 처음 호출하는 main()
static boolean[][] isVisited;
static int[][] board;
static int row, col;
//청소하는 칸의 개수
static int cnt;
//북 동 남 서 순서
static final int[] DIRECTIONS_ROW = {-1, 0, 1, 0};
static final int[] DIRECTIONS_COL = {0, 1, 0, -1};
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine() , " ");
row = Integer.parseInt(st.nextToken());
col = Integer.parseInt(st.nextToken());
st = new StringTokenizer(bf.readLine() , " ");
int startRow = Integer.parseInt(st.nextToken());
int startCol = Integer.parseInt(st.nextToken());
int startDirection = Integer.parseInt(st.nextToken());
board = new int[row][col];
isVisited = new boolean[row][col];
for (int i = 0; i < row; i++) {
st = new StringTokenizer(bf.readLine() , " ");
for (int j = 0; j < col; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}//for end
}//for end
//출발 장소 count
cnt++;
isVisited[startRow][startCol] = true;
//재귀함수 호출
dfs(startRow, startCol, startDirection);
//청소하는 칸의 개수 출력
System.out.println(cnt);
}
재귀 dfs()
현재 row, col, direction을 파라미터로 하는 재귀 메소드
90도씩 회전하면서 그 방향으로 이동 가능한지 확인
- 이동 가능하면 그 위치로 이동한 후 재귀 호출
- 이동 가능하지 않은 경우, 반대 방향 칸이 빈 칸이면 현재 방향을 유지한 채 반대 방향 칸으로 이동하고, 반대 방향 칸이 벽이면 중단
public static void dfs(int nowRow, int nowCol, int nowDirection) {
//빈 칸 0, 벽 1
//왼쪽으로 회전
int i = 1;
for (; i <= 4; i++) {
//새로운 방향
int newDirection = (nowDirection-i<0)? nowDirection-i+4 : nowDirection-i;
//새로운 방향으로 한 칸 이동
int newRow = nowRow + DIRECTIONS_ROW[newDirection];
int newCol = nowCol + DIRECTIONS_COL[newDirection];
//만일 새로 이동한 칸으로 진행할 수 있다면 이동!
//(방문 여부 true, 개수+1, 새로 이동한 칸에서 재귀 호출)
if ((newRow>0 && newRow<row-1)
&& (newCol>0 && newCol<col-1)
&& board[newRow][newCol] == 0
&& !isVisited[newRow][newCol]) {
cnt++;
isVisited[newRow][newCol] = true;
dfs(newRow, newCol, newDirection);
//현재 위치에서 어느 한 방향으로 이동했다면
//더 이상 현재 위치에서는 진행하지 않으므로 break
break;
}
}//for end
//모든 방향으로 더 이상 나갈 수 없을 때
if (i==5) {
//현재 방향의 반대 방향
int oppoDirection = (nowDirection+2>3)? nowDirection-2 : nowDirection+2;
//반대 방향으로 한 칸 이동
int newRow = nowRow + DIRECTIONS_ROW[oppoDirection];
int newCol = nowCol + DIRECTIONS_COL[oppoDirection];
//반대 방향으로 한 칸이 빈 칸이라면 이동!
if ((newRow>0 && newRow<row-1)
&& (newCol>0 && newCol<col-1)
&& board[newRow][newCol] == 0) {
dfs(newRow, newCol, nowDirection);
}//if end
}//if end
}//dfs() end
'자료구조 & 알고리즘 > 문제풀이' 카테고리의 다른 글
뉴스 클러스터링 - 2018 KAKAO BLIND RECRUITMENT (Java, Level 2) (0) | 2022.06.19 |
---|---|
[3차] 방금그곡 - 2018 KAKAO BLIND RECRUITMENT (Java, Level 2) (0) | 2022.06.19 |
가르침 - 백준 1062 (Java) (0) | 2022.06.08 |
암호코드 - 백준 2011 (Java) (0) | 2022.05.31 |
리모컨 - 백준 1107 (Java) (0) | 2022.05.31 |
댓글