ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 16928번 - 뱀과 사다리 게임
    알고리즘/백준 2023. 6. 27. 23:20

    1️⃣ Dijkstra Algorithm

     

    ✏️ 풀이 과정

    1로부터 100까지의 최단경로를 찾는 문제이기 때문에 다익스트라 알고리즘을 통해 해결할 수 있습니다. 다익스트라 알고리즘을 사용하면 한 출발점으로부터 다른 모든 정점으로의 최단 거리를 구할 수 있기 때문입니다. 알고리즘을 돌리고 배열에서 100에 대한 최단거리를 읽으면 답을 구할 수 있습니다.

     

    그래프로 바꿔보면 100개의 정점이 존재하는 것이기 때문에 이차원 배열을 사용하면 주사위로 갈 수 없는 정점이 대부분이라 연결되지 않은 정점이 많은 희소 행렬이 되어 낭비가 많아집니다. 이를 해결하기 위하여 인접 리스트를 사용하면 O(N^2) 대신 O(NlogN)의 시간복잡도로 문제를 해결할 수 있습니다. 이 때 문제의 조건을 반영하기 위해서 세 가지의 작업이 필요합니다.

     

    첫 번째로는 1에서 각 정점까지의 거리를 저장하는 일차원 배열을 선언하고 1에서의 다른 모든 정점에 대한 거리를 무한대(Integer.MAX_VALUE로 하면 더할 때 오버플로우가 나기 때문에 Integer.MAX_VALUE-100과 같은 적당히 큰 값으로 해야 합니다.)로 설정해야 합니다.

     

    두 번째는 주사위로 갈 수 있는 곳을 반영하기 위해서 모든 정점에 대해 1부터 6까지 더한 정점을 인접 리스트에 추가하여 연결 상태로 만들어주는 것입니다. 여기서는 Node 클래스를 설정하여 정점 번호와 가중치(거리)를 저장했습니다. 주사위로 갈 수 있는 경우 거리는 1이 됩니다. 주의할 점은 95부터는 for문을 따로 설정해주거나 처음 배열을 선언할 때 106개를 선언해야 에러가 발생하지 않습니다.

     

    마지막 세 번째는 뱀과 사다리를 반영하는 것입니다. 여기서 주의할 점은 뱀 혹은 사다리가 있는 칸에 갈 경우 반드시 타고 이동해야 한다는 것입니다. 즉 뱀이나 사다리가 있는 칸에 머무를 방법이 없습니다.(그 칸에서 주사위를 던지는 게 불가능합니다.) 이를 구현하기 위해서 뱀, 사다리가 있는 칸을 주사위로 갈 수 있는 모든 칸에 대해 인접 리스트에서 이동 장소로 향하는 가중치 1짜리 노드를 추가해야 합니다. 또한 뱀이나 사다리가 있는 정점들은 Integer.MIN_VALUE로 설정하여 다익스트라 알고리즘 적용 중 생성된 최적이 아닌 중간 값 제거를 위한 매커니즘에(거리가 현재까지 구한 최적 거리보다 큰 경우) 걸러지게 만듭니다.

     

    위 작업들을 마치고 PriorityQueue를 사용해서 다익스트라 알고리즘을 돌리면 dist[100]에서 답을 얻어낼 수 있습니다.

     

    💻 코드

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.PriorityQueue;
    import java.util.StringTokenizer;
    
    public class Main {
    	
    	static class Node implements Comparable<Node> {
    		int v;
    		int dist;
    		Node link;
    		
    		public Node(int v, int dist, Node link) {
    			this.v = v;
    			this.dist = dist;
    			this.link = link;
    		}
    		
    		@Override
    		public int compareTo(Node o) {
    			return this.dist - o.dist;
    		}
    	}
    	
    	public static void main(String[] args) throws IOException {
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		StringTokenizer st = new StringTokenizer(br.readLine());
    		int N = Integer.parseInt(st.nextToken());
    		int M = Integer.parseInt(st.nextToken());
    		Node[] adjList = new Node[101];
    		int[] dist = new int[101];
    		for(int i=2;i<=100;i++) {
    			dist[i] = Integer.MAX_VALUE - 100;
    		}
    		for(int i=1;i<=94;i++) {
    			for(int j=1;j<=6;j++) {
    				adjList[i] = new Node(i+j, 1, adjList[i]);
    			}
    		}
    		for(int i=95;i<=99;i++) {
    			for(int j=1;j<=6-i+94;j++) {
    				adjList[i] = new Node(i+j, 1, adjList[i]);
    			}
    		}
    		int from, to;
    		for(int i=0;i<N;i++) {
    			st = new StringTokenizer(br.readLine());
    			from = Integer.parseInt(st.nextToken());
    			to = Integer.parseInt(st.nextToken());
    			dist[from] = Integer.MIN_VALUE;
    			for(int j=from-6;j<=from-1;j++) {
    				if(j >= 0) {
    					adjList[j] = new Node(to, 1, adjList[j]);
    				}
    			}
    		}
    		for(int i=0;i<M;i++) {
    			st = new StringTokenizer(br.readLine());
    			from = Integer.parseInt(st.nextToken());
    			to = Integer.parseInt(st.nextToken());
    			dist[from] = Integer.MIN_VALUE;
    			for(int j=from-6;j<=from-1;j++) {
    				if(j >= 0) {
    					adjList[j] = new Node(to, 1, adjList[j]);
    				}
    			}
    		}
    		PriorityQueue<Node> pq = new PriorityQueue<>();
    		Node cur;
    		pq.offer(new Node(1, 0, null));
    		while(!pq.isEmpty()) {
    			cur = pq.poll();
    			if(dist[cur.v] < cur.dist) {
    				continue;
    			}
    			for(Node n=adjList[cur.v];n!=null;n=n.link) {
    				if(dist[n.v] > dist[cur.v] + n.dist) {
    					dist[n.v] = dist[cur.v] + n.dist;
    					pq.offer(new Node(n.v, dist[cur.v] + n.dist, null));
    				}
    			}
    		}
    		System.out.println(dist[100]);
    		br.close();
    	}
    }

     

    2️⃣ BFS

     

    문제 분류를 보니 원래는 BFS로 해결하는 문제인 듯 합니다. 향후 시간이 나면 업데이트하겠습니다. 단계 수를 체크하는 BFS로 뱀과 사다리에서 순간이동 처리를 해주고 100에 도달하는 순간 종료하여 문제를 해결할 수 있을 것으로 보여집니다.

    '알고리즘 > 백준' 카테고리의 다른 글

    21736번 - 헌내기는 친구가 필요해  (0) 2023.06.28
    18870번 - 좌표 압축  (0) 2023.06.27
    14940번 - 쉬운 최단거리  (0) 2023.06.26
    14500번 - 테트로미노  (0) 2023.06.26
    17626번 - Four Squares  (0) 2023.06.25
Designed by Tistory.