알고리즘

프로그래머스 지형 이동 (JAVA)

박카스마시며코딩 2022. 6. 1. 13:48

https://programmers.co.kr/learn/courses/30/lessons/62050

 

코딩테스트 연습 - 지형 이동

[[1, 4, 8, 10], [5, 5, 5, 5], [10, 10, 10, 10], [10, 10, 10, 20]] 3 15 [[10, 11, 10, 11], [2, 21, 20, 10], [1, 20, 21, 11], [2, 1, 2, 1]] 1 18

programmers.co.kr

 

저는 해당 문제를 크루스칼을 통해서 문제를 해결하였습니다.

일단 시작점이나 끝점에 대해서 정해져있지 않아서 BFS나 DFS를 하기에 시간복잡도가 너무 커질 것이라 생각하였습니다.

저는 각 점들이 어떻게된 연결만 된다고 생각하여 MST를 생각하여 크루스칼로 해결하는 방법을 생각하였습니다.

각 점에서 4방탐색하여 각 점을 연결할 때의 가중치를 저장하고 이를 오름차순으로 정렬하고 각 점들을 연결하면서 연결괴면 height크다면 가중치를 더 해주는 방법으로 문제를 해결하였습니다.

 

import java.util.*;
class Solution {
    private int[] makeParent(int[][] land,int size){
        int[] parent = new int[size*size];
        for(int i = 0 ; i < size*size ; i++){
            parent[i] = i;
        }
        return parent;
    }
    public int solution(int[][] land, int height) {
        int answer = kruskal(land,height);
        return answer;
    }
    private int findSet(int num, int[] parent){
        if(num == parent[num]){
            return num;
        }
        return parent[num] = findSet(parent[num], parent);
    }
    private boolean unionSet(int a, int b, int[] parent){
        int aParent = findSet(a,parent);
        int bParent = findSet(b,parent);
        if(aParent == bParent){
            return false;
        }
        parent[aParent] = bParent;
        return true;
    }
    private int findPosition(int y, int x, int size){
        return y * size + x;
    }
    private boolean checkBound(int y,int x,int size){
        if(y >= 0 && y < size && x >= 0 && x < size){
            return true;
        }
        return false;
    }
    
    private static int[] dy = {-1,0,1,0};
    private static int[] dx = {0,1,0,-1};
    
    private int kruskal(int[][] land, int height){
        int size = land.length;
        int[] parent = makeParent(land,size);
        List<int[]> list = new LinkedList<>();
        // System.out.println(Arrays.toString(parent));
        for(int y = 0 ; y < size ; y++){
            for(int x = 0 ; x < size; x++){
                 for(int dir = 0 ; dir < 4 ; dir++){
                     int ny = y + dy[dir];
                     int nx = x + dx[dir];
                     if(!checkBound(ny,nx,size)){
                         continue;
                     }
                     int weight = Math.abs(land[ny][nx] - land[y][x]);
                     if(weight <= height){
                         weight = 0;
                     }
                     list.add(new int[] {y,x,ny,nx,weight});
                 }
            }
        }
        Collections.sort(list,(o1,o2)->{
            return o1[4] - o2[4];
        });
        // list.stream().map(Arrays::toString).forEach(System.out::println);
        int result = 0;
        for(int[] arr : list){
            int startPosition = findPosition(arr[0], arr[1], size);
            int endPosition = findPosition(arr[2], arr[3], size);
            if(unionSet(startPosition,endPosition,parent)){
                result += arr[4];
            }
        }
        return result;
    }
}