ABOUT ME

Trust your instincts!

Today
Yesterday
Total
  • 백준 20058, 프로그래머스 - 섬 연결하기, 보석쇼핑
    Java/코딩테스트 2023. 7. 12. 08:30

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

     

    20058번: 마법사 상어와 파이어스톰

    마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c

    www.acmicpc.net

    * 삼성 기출문제 (시뮬레이션, 구현, 탐색) 

     

    1. 단계를 입력받고 칸을 나눈다. 참고로 이때 바로 원본배열에 적용하면 안된다. (동시에 녹이고 반영해야하므로)

    2. 각 격자를 회전시키는 함수 수행 

    3. 얼음 녹이기 (모든 얼음은 동시에 녹아야 한다!!!! 꼭 기억할 것!)

    4. 다 끝나면 덩어리 출력

     

    이런 문제의 경우 미리 각 움직임을 dirX, dirY 배열에 정의해두면 편하다.

    ! 배열을 회전하는 함수도 종종 문제에서 출제되므로 이번 기회에 외워두기 

    ! 얼음 한번에 녹는다는 것을 꼭 기억. 바로 원본배열 건드리면 안된다. 삼성기출에서 이런 유형이 자주 나온다. 

    public class p20058 {
        public static int[][] graph;
        public static int[] step;
        public static int[] dirX = { 0, 1, 0, -1 };
        public static int[] dirY = { -1, 0, 1, 0 };
        public static int size, answerIce, answerSize;
    
        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 q = Integer.parseInt(st.nextToken());
            size = (int) Math.pow(2, n);
            graph = new int[size][size];
            for (int i = 0; i < size; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < size; j++) {
                    graph[i][j] = Integer.parseInt(st.nextToken());
                }
            }
    
            step = new int[q];
            st = new StringTokenizer(br.readLine());
            for (int i = 0; i < q; i++) {
                step[i] = Integer.parseInt(st.nextToken());
            }
    
            for (int i = 0; i < q; i++) {
                graph = divide(step[i]); // 단계에 맞게 칸 나누고 회전 시키기
                graph = melt(); // 녹인 결과 저장
            }
            answerIce = answerSize = 0;
            find();
    
            System.out.println(answerIce);
            System.out.println(answerSize);
    
    
        }
    
        public static int[][] divide(int steps) {
            int[][] temp = new int[size][size];
            steps = (int) Math.pow(2, steps);
            for (int i = 0; i < size; i += steps) {
                for (int j = 0; j < size; j += steps) {
                    rotateRight(i, j, steps, temp);
                }
            }
            return temp;
        }
    
        public static void rotateRight(int x, int y, int size, int[][] temp) {
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    temp[x+i][y+j] = graph[x+size-1-j][y+i];
                }
            }
        }
    
        public static int[][] melt() {
            int[][] temp = new int[size][size];
            for (int i = 0; i < size; i++) {
                temp[i] = Arrays.copyOf(graph[i], size);
            }
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    int count = 0;
                    if (graph[i][j] == 0) {
                        continue;
                    }
                    for (int k = 0; k < 4; k++) {
                        int nextX = i + dirX[k];
                        int nextY = j + dirY[k];
                        if (nextX >= 0 && nextX < size && nextY >= 0 && nextY < size && graph[nextX][nextY] > 0) {
                            count++;
                        } // 현 좌표에서 4방향 탐색. 유효 범위내 좌표이고, 얼음이 있다면 count 증가
                    }
                    if (count < 3) {
                        temp[i][j]--; 
                    }
                }
            }
            return temp;
        }
    
        public static void find() {
            Queue<Pos> queue = new LinkedList<>();
            boolean[][] visited = new boolean[size][size];
    
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    answerIce += graph[i][j]; // 모든 칸의 얼음 다 더한값이 answerIce
                    if (graph[i][j] > 0 && !visited[i][j]) {
                        queue.offer(new Pos(i, j));
                        visited[i][j] = true;
                        int count = 1;
    
                        while (!queue.isEmpty()) {
                            Pos pos = queue.poll();
    
                            for (int k = 0; k < 4; k++) {
                                int nextX = pos.x + dirX[k];
                                int nextY = pos.y + dirY[k];
                                if (nextX >= 0 && nextX < size && nextY >= 0 && nextY < size && graph[nextX][nextY] > 0 && !visited[nextX][nextY]) {
                                    queue.offer(new Pos(nextX, nextY));
                                    visited[nextX][nextY] = true;
                                    count++;
                                }
                            }
                        }
                        answerSize = Math.max(answerSize, count); // 가장 큰 얼음 칸 개수
                    }
                }
            }
    
        }
    
        static class Pos {
            int x;
            int y;
            public Pos(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    }

     


    https://school.programmers.co.kr/learn/courses/30/lessons/42861

     

    프로그래머스

    코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

    programmers.co.kr

    * Greedy 알고리즘 

    * 우선순위큐에 넣어서 자동으로 에지 값 순서로 정렬시키고(에지 가중치 작은 순 정렬) 하나씩 꺼내면서 다리를 놓는다. 다리를 놓을 수 있는 최대 개수는 노드-1이므로 edgeCount값을 n-1로 지정해놓은 것. (노드-1인 경우는 일직선으로 쭉 연결된 경우) 

     

    import java.util.*;
    public class 섬연결하기 {
        class Solution {
            public int[] union;
            public int solution(int n, int[][] costs) {
                PriorityQueue<Edge> queue = new PriorityQueue<>();
                union = new int[n];
                int edgeCount = n-1;
                int answer = 0;
    
                for (int i = 0; i < n; i++) {
                    union[i] = i;
                }
                for (int i = 0; i < costs.length; i++) {
                    queue.add(new Edge(costs[i][0], costs[i][1], costs[i][2]));
                }
    
    
                while (edgeCount > 0) {
                    Edge e = queue.poll();
                    int a = findNode(e.start);
                    int b = findNode(e.end);
                    if (a != b) {
                        unionNode(a, b);
                        answer += e.weight;
                        edgeCount--;
                    }
                }
                return answer;
            }
    
            public void unionNode(int a, int b) {
                int findA = findNode(a);
                int findB = findNode(b);
                if (findA != findB) {
                    union[findB] = findA;
                }
            }
    
            public int findNode (int n) {
                if (union[n] == n) {
                    return n;
                } else {
                    return union[n] = findNode(union[n]);
                }
            }
    
            public class Edge implements Comparable<Edge> {
                int start;
                int end;
                int weight;
    
                public Edge (int s, int e, int w) {
                    this.start = s;
                    this.end = e;
                    this.weight = w;
                }
    
                public int compareTo(Edge e) {
                    return this.weight < e.weight ? -1 : 1;
                }
    
            }
        }
    }

     

     

     

     

     

     

     

    https://school.programmers.co.kr/learn/courses/30/lessons/67258

     

    프로그래머스

    코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

    programmers.co.kr

    * two-pointer 알고리즘 문제 

    * Set, Map 에 대해 알고 있을 것.

    중복 없이 각 값만 저장하고, 순서는 중요하지 않으므로 Set 사용.

    각 보석별 개수는 Map에 저장. (보석종류, 개수)의 형태로 저장한다. 

     

     

    import java.util.*;
    public class 보석쇼핑 {
        class Solution {
            public int[] solution(String[] gems) {
                int start = 0;
                int end = 0;
                int startAnswer = 0;
                int endAnswer = gems.length-1;
    
                // 보석 종류를 먼저 저장해두기, 종류 그 자체를 저장하므로 HashSet
                Set<String> gemType = new HashSet<>(Arrays.asList(gems));
                Map<String, Integer> tempGem = new HashMap<>();
    
                tempGem.put(gems[start], 1);
                while (start < gems.length) {
                    if (tempGem.keySet().size() == gemType.size()) { // 현재 모든 보석이 다 들어있다면
                        if (end - start < endAnswer - startAnswer) {
                            startAnswer = start;
                            endAnswer = end;
                        } // 현재 거리가 더 짧다면 startAnswer, endAnswer 갱신 
                        // 시작점 옮겨주고 시작점 보석을 줄임
                        tempGem.put(gems[start], tempGem.get(gems[start]) - 1);
                        // 0개라면 해당 보석 종류 제거
                        if (tempGem.get(gems[start]) == 0) {
                            tempGem.remove(gems[start]);
                        }
                        start++;
                    }
                    else if (end < gems.length - 1) { // 그게 아니라면 end를 뒤로 보내서 한 칸씩 늘린다
                        end++;
                        if (tempGem.get(gems[end]) == null) {
                            tempGem.put(gems[end], 1);
                        }
                        else {
                            tempGem.put(gems[end], tempGem.get(gems[end]) + 1);
                        }
    
                    }
                    else {
                        break;
                    }
                }
                return new int[] { startAnswer + 1, endAnswer+1 };
            }
        }
    }

     

     

     

    'Java > 코딩테스트' 카테고리의 다른 글

    코딩테스트 직전 정리  (0) 2023.07.23
    백준 1149, 12852, 17135  (0) 2023.07.21
    백준 2579, 11057 - JAVA  (0) 2023.07.05
    백준 11048 - Java  (0) 2023.06.29
    백준 9205 - Java  (0) 2023.06.29
Designed by Tistory.