[백준/Java] 1261 - 알고스팟

2025. 10. 1. 22:37·코딩테스트/백준

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

문제


풀이

가중치가 0 또는 1인 그래프에서 시작점부터 도착점까지의 최단 경로(최소 가중치 합)을 구하는 문제이다

가중치가 있는 그래프의 최단 경로는 보통 다익스트라 알고리즘을 사용한다

하지만 이 문제처럼 가중치가 0과 1로만 이루어져 있으면 더 간단한 `0-1 BFS 기법`을 사용할 수 있다

 

0-1 BFS

  • 일반 큐 대신 덱(Deque)을 사용한다
  • 가중치가 0인 간선으로 탐색할 때는 다음 정점을 덱의 앞에 넣는다
  • 가중치가 1인 간선으로 탐색할 때는 다음 정점을 덱의 뒤에 넣는다

이렇게 하면 항상 가중치가 0인 경로를 먼저 처리할 수 있다

벽을 부수지 않고 갈 수 있는 모든 곳을 먼저 가고 다음에 벽을 부수는 경로를 탐색한다

 

자세한 것은 코드를 보자

코드

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

public class Main {

	static int N, M;

	static int[][] arr;
	static int[][] visited; // 방문 + 벽 파괴 횟수 저장

	static int[] dx = {-1, 1, 0, 0}; // 상하
	static int[] dy = {0, 0, -1, 1}; // 좌우

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		StringBuilder sb = new StringBuilder();

		st = new StringTokenizer(br.readLine());
		M = Integer.parseInt(st.nextToken());
		N = Integer.parseInt(st.nextToken());
		arr = new int[N][M];
		visited = new int[N][M];

		// 배열 입력
		for (int i = 0; i < N; i++) {
			String str = br.readLine();
			for (int j = 0; j < M; j++) {
				arr[i][j] = str.charAt(j) - '0';
				visited[i][j] = Integer.MAX_VALUE; // 각 위치의 최솟값을 찾기 위해 큰 값 초기 설정
			}
		}

		bfs(); // bfs 호출

		// bfs를 다 돌면 벽 파괴 횟수가 저장되어 있음
		System.out.println(visited[N - 1][M - 1]);
		br.close();
	}

	static void bfs() {
		Deque<int[]> queue = new ArrayDeque<>(); // 우선순위를 위해 Deque 사용
		queue.add(new int[]{0, 0}); // 시작 위치 큐에 추가
		visited[0][0] = 0; // 방문 처리

		while (!queue.isEmpty()) {
			int[] cur = queue.poll(); // 큐에서 하나씩 뺌
			int cx = cur[0];
			int cy = cur[1];

			// 상하좌우 탐색
			for (int i = 0; i < 4; i++) {
				int nx = cx + dx[i];
				int ny = cy + dy[i];

				// 범위 밖이면 continue
				if(nx < 0 || nx > N - 1 || ny < 0 || ny > M - 1) continue;

				// 방문하지 않았다면
				if (visited[nx][ny] == Integer.MAX_VALUE) {
					// 배열 값이 0이면
					if (arr[nx][ny] == 0) {
						// 현재 경로가 더 효율적이면
						if (visited[cx][cy] < visited[nx][ny]) {
							visited[nx][ny] = visited[cx][cy]; // 다음 경로 갱신
							queue.addFirst(new int[]{nx, ny}); // 큐의 맨 앞에 추가
							// 항상 가중치가 0인 것부터 체크
						}
					} else { // 배열 값이 1이면 벽을 부숴야함
						// 현재 경로가 더 효율적이면
						if (visited[cx][cy] + 1 < visited[nx][ny]) {
							visited[nx][ny] = visited[cx][cy] + 1; // 다음 경로 갱신
							queue.addLast(new int[]{nx, ny}); // 큐의 맨 뒤에 추가
						}
					}

				}

			}
		}
	}

}

결과

'코딩테스트/백준' 카테고리의 다른 글
  • [백준/Java] 9663 - N-Queen
  • [백준/Java] 2447 - 별 찍기 - 10
  • [백준/Java] 13913 - 숨바꼭질 4
  • [백준/Java] 2206 - 벽 부수고 이동하기
KDH.dev
KDH.dev
  • KDH.dev
    CodingHard
    KDH.dev
  • 전체
    오늘
    어제
    • 전체글 (82)
      • 코딩테스트 (74)
        • 프로그래머스 (13)
        • 백준 (61)
      • CS (4)
        • 네트워크 (4)
      • Spring (1)
      • Java (3)
        • 자료구조 (3)
        • 알고리즘 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    CS
    프로그래머스 Lv.0
    16935
    부트캠프후기
    멀티캠퍼스it부트캠프
    자료구조
    14940
    13913
    코딩테스트
    자바
    18111
    30804
    11660
    5525
    17626
    백준
    [LG유플러스] 유레카 백엔드 개발자
    21736
    네트워크
    프로그래머스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
KDH.dev
[백준/Java] 1261 - 알고스팟
상단으로

티스토리툴바