[SWEA] 4193: 수영대회 결승전 (JAVA)

2024. 7. 4. 22:19·Algorithm/완전탐색

문제

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

여담

진짜 바보인가? 왜 자꾸 중요한 조건을 놓쳐서 틀리는걸까 ㅎㅎ.... 풀이 방식 잘 생각해놓고 이렇게 어이없이 틀릴 때마다 답답..

 

제발 문제를 똑바로 다 읽고 정리하고 끝까지 확인하는 습관을 가지자!!!

 

풀이

N의 범위(2 ≤ N ≤ 15)도 크지 않기 때문에 완전탐색 방식으로 문제를 풀었다. (다른 풀이를 찾아보니 BFS 방식으로도 풀 수 있는 듯 하다. 이건 나중에..)

 

가장 고려해야 할 부분은 소용돌이 장애물이다. 소용돌이 장애물은 2초마다 나타나고 1초 사라지는 형식을 띄고 있다.

  • 0초&1초: 나타남, 2초: 사라짐, 3초&4초: 나타남, 5초: 사라짐, ...

이를 0초가 아닌 1초부터 시작한다고 가정하면 3의 배수일 때마다 소용돌이 장애물이 사라지는 것이 된다.

  • 1초&2초: 나타남, 3초: 사라짐, 4초&5초: 나타남, 6초: 사라짐, ...

 

이를 바탕으로 현재 n초일 때 소용돌이가 사라지기 전까지 기다려야 하는 시간의 식을 세우면 (n / 3 + 1) * 3 - n이다.

  • n = 2
    • (2 / 3 + 1) * 3 - 2 = 3 - 2 = 1초 기다려야 함
  • n = 4
    • (4 / 3 + 1) * 3 - 4 = 6 - 4 = 2초 기다려야 함

 

따라서 이를 바탕으로 완전 탐색을 수행하면 된다. 완전탐색을 수행하는 로직은 다음과 같다.

  • 만약 도착지에 도착했다면, 값을 갱신하고 탐색을 종료하기
    • minDist = Math.min(minDist, dist - 1) (1초부터 시작했으니, 1을 빼고 비교해야 함)
  • 만약 현재 minDist 값보다 dist 값이 크다면 탐색을 종료하기
    • 가장 빠른 길을 찾아야 하므로, 현재 찾은 빠른 길보다 길면 의미 없음
  • 네 방향으로 이동하기
    • 범위를 벗어나거나 장애물이 있다면 해당 칸으로 이동하지 않기
    • 만약 소용돌이가 나타나는 위치이고, 현재 소용돌이가 있다면 기다리기(위의 식을 통해 얻은 값만큼)
    • 백트래킹을 위해 "방문 처리 → 재귀호출 → 방문 처리 취소"를 수행하기

 

자세한 내용은 코드를 참고하면 된다.

 

코드

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

class Solution {
    static int N, A, B, C, D, minDist;
    static int[][] map;
    static boolean[][] visited;
    static final int INF = Integer.MAX_VALUE;
    static int[][] move = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        for (int t = 1; t <= T; t++) {
            N = Integer.parseInt(br.readLine());
            map = new int[N][N];
            visited = new boolean[N][N];
            for (int i = 0; i < N; i++) {
                StringTokenizer st = new StringTokenizer(br.readLine(), " ");
                for (int j = 0; j < N; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                }
            }
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            A = Integer.parseInt(st.nextToken());
            B = Integer.parseInt(st.nextToken());
            st = new StringTokenizer(br.readLine(), " ");
            C = Integer.parseInt(st.nextToken());
            D = Integer.parseInt(st.nextToken());

            minDist = INF;
            dfs(1, A, B);
            if (minDist == INF) minDist = -1; // 도착할 수 없다면 -1 출력
            sb.append("#").append(t).append(" ").append(minDist).append("\n");
        }
        System.out.println(sb.toString());
    }

    static void dfs(int dist, int x, int y) {
        if (x == C && y == D) { // 도착지에 도착하면 탐색 종료
            minDist = Math.min(minDist, dist - 1);
            return;
        }
        // 기록된 최소 이동 시간보다 길면 탐색할 필요 없음
        if (minDist < dist) return;
        // 네 방향으로 이동하기
        for (int i = 0; i < 4; i++) {
            int nx = x + move[i][0];
            int ny = y + move[i][1];
            // 범위 벗어남 or 이미 방문 or 장애물이 있는 경우 탐색 X
            if (nx < 0 || ny < 0 || nx >= N || ny >= N || visited[nx][ny] || map[nx][ny] == 1) {
                continue;
            }
            // 문제 이해 잘못했음.. 가려고 하는 곳에 소용돌이가 있으면 없어질 때까지 기다리고 이동해야 함

            visited[nx][ny] = true;
            int time = 1;
            if (map[nx][ny] == 2 && dist % 3 != 0) { // 소용돌이가 사라지지 않았다면 사라질 때까지 기다려야 함
                time += (dist / 3 + 1) * 3 - dist;
            }
            dfs(dist + time, nx, ny);
            visited[nx][ny] = false;
        }
    }
}

 

'Algorithm > 완전탐색' 카테고리의 다른 글

[BOJ] 14889: 스타트와 링크 (JAVA)  (0) 2024.09.22
[BOJ] 14500: 테트로미노 (JAVA)  (1) 2024.09.16
[BOJ] 2961: 도영이가 만든 맛있는 음식 (JAVA)  (0) 2024.05.21
[BOJ] 14620: 꽃길 (JAVA)  (0) 2024.05.20
[BOJ] 2615: 오목 (JAVA)  (0) 2024.05.11
'Algorithm/완전탐색' 카테고리의 다른 글
  • [BOJ] 14889: 스타트와 링크 (JAVA)
  • [BOJ] 14500: 테트로미노 (JAVA)
  • [BOJ] 2961: 도영이가 만든 맛있는 음식 (JAVA)
  • [BOJ] 14620: 꽃길 (JAVA)
hjin28
hjin28
  • hjin28
    끄적이는 기록장
    hjin28
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • 홈
    • 태그
    • GitHub
    • 이전 블로그
    • 분류 전체보기
      • TIL
      • Frontend
      • Backend
      • Infra
      • Java
        • 이것이 자바다
      • CS
        • 컴퓨터구조
        • 운영체제
        • 네트워크
        • 데이터베이스
      • Algorithm
        • 자료구조
        • 시뮬레이션
        • 완전탐색
        • BFS & DFS
        • DP
        • 그리디
        • 최단경로
        • 유니온파인드
        • 위상정렬
        • 정렬
        • SQL
      • ETC
  • 최근 글

  • 태그

    비트마스킹
    java
    자료구조
    위상정렬
    ec2
    완전탐색
    컴퓨터구조
    vue
    SWEA
    백트래킹
    CS
    최단경로
    SQL
    그리디
    JWT
    유니온파인드
    자바
    springsecurity
    다이나믹프로그래밍
    구현
    백준
    Spring
    덱
    DP
    til
    BFS
    투포인터
    websocket
    DFS
    Programmers
  • hELLO· Designed By정상우.v4.10.1
hjin28
[SWEA] 4193: 수영대회 결승전 (JAVA)
상단으로

티스토리툴바