ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 1027, 14502
    Java/코딩테스트 2023. 7. 30. 19:01

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

     

    1027번: 고층 건물

    세준시에는 고층 빌딩이 많다. 세준시의 서민 김지민은 가장 많은 고층 빌딩이 보이는 고층 빌딩을 찾으려고 한다. 빌딩은 총 N개가 있는데, 빌딩은 선분으로 나타낸다. i번째 빌딩 (1부터 시작)

    www.acmicpc.net

    - 기울기 계산하는 공식이 필요한 문제 

    - 처음에는 오른쪽 왼쪽 다 계산하게끔 만들었는데, 그럴 필요 없이 그냥 한 방향으로 쭉 탐색할 수 있었다. 

    - 일단 이웃하는 애는 무조건 보이고, 내 쪽에서 보인다는 뜻은 반대편에서도 내 쪽이 보인다는 뜻이므로 한 방향으로 탐색할 때 양쪽을 같이 증가시켜주면 된다. 

     

    이 문제는 진짜 ... 계속 뭐가 안 되는건지 원인을 잘 못찾아서 푸는데 오래 걸렸던 문제이다.

     

    🏙 일단 slope 갱신 관련한 실수이다.

    ------ 처음에는 무조건 slope 갱신하도록 코드를 짰었다.

    = 반례 )  빌딩 높이가  2 3 1 4 이런식으로 갈때 2의 입장에서 1은 어차피 3에 가려져서 안 보인다. 즉, 높이가 1인 빌딩을 바라볼 때 경사도가 아닌, 더 높은 값인 3보다 높은지 낮은지를 따져야 함
    🏙 또한 slope 계산시 자료형 문제이다.

    ----- int형이 아닌, Double로 계산해주는 것 빼먹지 말것... 빌딩의 높이와 인덱스는 정수형이지만 계산 결과는 double로 따져야하므로.. 

     

    import java.io.*;
    import java.util.*;
    
    public class p1027 {
        static int[] buildings;
        public static void main(String[] args) throws IOException{
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int n = Integer.parseInt(br.readLine());
    
            StringTokenizer st = new StringTokenizer(br.readLine());
            buildings = new int[n];
            int[] answer = new int[n];
    
            for (int i = 0; i < n; i++) {
                buildings[i] = Integer.parseInt(st.nextToken());
            }
    
            for (int i = 0; i < n-1; i++) {
    
                // 이웃하는 빌딩은 무조건 보임
                double slope = calculate(i, i+1);
    
                // answer[] ~ i는 i+1입장에서 보이므로 +1 (오른쪽에서 보이면 왼쪽도 반대로 볼 수 있다는 뜻)
                answer[i]++;
                answer[i+1]++;
    
                for (int j = i+2; j < n; j++) {
                    double tempSlope = calculate(i, j);
                    if (slope < tempSlope) {
                        slope = tempSlope; 
                        answer[i]++;
                        answer[j]++;
                    }
    
                }
    
            }
    
            int highest = Integer.MIN_VALUE;
            for (int i = 0; i < n; i++) {
                highest = Math.max(highest, answer[i]);
            }
    
            System.out.println(highest);
    
        }
    
        public static double calculate(int left, int right) {
            return (double) (buildings[right] - buildings[left])/ (right - left);
        }
    
    }

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

     

    14502번: 연구소

    인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

    www.acmicpc.net

    생각보다 금방 푼(?) 문제이다. 아마 이전에 연구소 시리즈 문제를 풀었어서 그런듯 하다. 전형적인 삼성st 기출문제이다. 

     

    벽을 세울 수 있는 칸은 0인 칸이고, 2인 칸은 바이러스가 있는 칸이다. 

    벽의 후보인 칸이랑, 바이러스 칸은 ArrayList에 미리 담아두었다. 

     

    DFS 돌리면서 벽 후보 리스트에서 3칸 선정하고, 선정 끝나면 바이러스 퍼트리는 BFS 수행하면 된다. 

    이 벽 세우는거랑 바이러스 퍼뜨리는 것도 당연히 원본배열 손대면 안된다. 

     

     

    import java.util.*;
    import java.io.*;
    public class p14502 {
        static int[] dirX = { -1, 1, 0, 0};
        static int[] dirY = { 0, 0, -1, 1};
        static int[][] map;
        static int row;
        static int column;
        static int empty; // 빈 칸 개수
        static int answer;
        static ArrayList<Pos> canBeWall;
        static ArrayList<Pos> virus;
        static boolean[] selected;
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(br.readLine());
    
            row = Integer.parseInt(st.nextToken());
            column = Integer.parseInt(st.nextToken());
    
            map = new int[row][column];
            canBeWall = new ArrayList<>();
            virus = new ArrayList<>();
            empty = 0;
            answer = Integer.MIN_VALUE;
    
            for (int i = 0; i < row; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < column; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                    if (map[i][j] == 0) {
                        canBeWall.add(new Pos(i, j));
                        empty++;
                    }
                    else if (map[i][j] == 2) {
                        virus.add(new Pos(i, j));
                    }
                }
            }
            selected = new boolean[empty];
    
            DFS(0, 0);
            System.out.println(answer);
        }
    
        public static int BFS() {
            Queue<Pos> queue = new LinkedList<>();
            boolean[][] visited = new boolean[row][column];
            int[][] temp = new int[row][column];
    
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < column; j++) {
                    temp[i][j] = map[i][j];
                }
            }
    
            // 가벽 세우기
            for (int i = 0; i < selected.length; i++) {
                if (!selected[i]) {
                    continue;
                } else {
                    Pos pos = canBeWall.get(i);
                    temp[pos.x][pos.y] = 1;
                }
            }
    
            int count = 0;
            for (Pos pos : virus) {
                queue.add(pos);
            }
    
            while (!queue.isEmpty()) {
                Pos poll = queue.poll();
    
                for (int i = 0; i < 4; i++) {
                    int nextX = poll.x + dirX[i];
                    int nextY = poll.y + dirY[i];
    
                    if (!isValid(nextX, nextY)) {
                        continue;
                    }
                    if (visited[nextX][nextY]) {
                        continue;
                    }
    
                    if (temp[nextX][nextY] == 1) {
                        continue;
                    }
    
                    queue.add(new Pos(nextX, nextY));
                    temp[nextX][nextY] = 2;
                    visited[nextX][nextY] = true;
                }
            }
    
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < column; j++) {
                    if (temp[i][j] == 0) {
                        count++;
                    }
                }
            }
    
            return count;
        }
    
        public static void DFS(int cur, int depth) {
            if (depth == 3) {
                answer = Math.max(BFS(), answer);
                return;
            }
            for (int i = cur; i < empty; i++) {
                selected[i] = true;
                DFS(i+1, depth+1);
                selected[i] = false;
            }
        }
    
        public static boolean isValid(int x, int y) {
            return x >= 0 && x < row && y >= 0 && y < column;
        }
    
        static class Pos {
            int x;
            int y;
            Pos(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    }

     

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

    프로그래머스 구명보트, 조이스틱  (0) 2023.08.07
    백준 15486, 14658  (0) 2023.08.02
    백준 17070, 2212, 12018, 14719  (0) 2023.07.26
    코딩테스트 직전 정리  (0) 2023.07.23
    백준 1149, 12852, 17135  (0) 2023.07.21
Designed by Tistory.