Java/코딩테스트

백준 20055

Bubbles 2023. 10. 13. 19:36

🤖 백준 20055 : 컨베이어 벨트 위의 로봇

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

 

20055번: 컨베이어 벨트 위의 로봇

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부

www.acmicpc.net

🤖 쉬웠는데, 딱 한 조건 빼먹어서 고생한 문제...부들부들... 

🤖 나는 컨베이어벨트가 두 줄이고, 첫 줄의 마지막 원소를 두 번째 줄의 마지막에, 두 번째 줄의 첫 원소를 첫 줄의 맨 앞에 넣는 것을 보고 LinkedList를 사용하면 되겠다고 생각했다. 

🤖 그리고 문제 조건에서 보면 알겠지만, 결국 로봇은 첫 줄에서만 움직인다. 그래서 로봇은 크기가 n인 배열로 만들었다. 

🤖 그리고, 문제 읽어보면 당연히 로봇 먼저 올리고 컨베이어 벨트 회전하는건줄 알았는데, 그게 아니라고 한다... 문제가 약간 말을 꼬아놓은 느낌이 있다.

🤖 과정  (while 문안에서 이대로 수행, while 조건은 내구도 0인 칸의 개수가 k보다 작다면) 

  • 컨베이어 벨트 회전(회전에 의해 로봇도 한칸씩 이동, 이때는 내구도 그대로)
  • 움직일 수 있는 로봇 움직임(움직일 경우 내구도 감소)
  • 로봇 올림 

🤖 자료구조들

private static LinkedList<Integer> first;
private static LinkedList<Integer> second;
private static int[] robots;
private static int n, k, robotCount;
  • robots를 굳이 Int로 안해도 된다. boolean으로 해도 상관없다. 
  • 로봇 번호를 굳이 카운트할 필요 없는데, 처음에 있다고 생각해서 int[] robots, robotCount 변수를 만들어뒀었다.
  • boolean[] robots, int n, k 이렇게 있으면 될듯
  • first, second는 각 칸 내구도가 들어간다고 생각하면 된다! 

 

🤖 문제로직 

while (zeroCount() < k) {
    rotateBelt();
    robotSelfMove();
    onRobot();
    step++;
}

🤖 rotateBelt() : 컨테이너 벨트 회전 

static void rotateBelt() {
    int secondFirst = second.removeFirst();
    int firstLast = first.removeLast();

    first.addFirst(secondFirst);
    second.addLast(firstLast);

    // 첫 줄 마지막 칸 도착한 로봇은 내림
    for (int i = n-2; i >=0; i--) {
        robots[i+1] = robots[i];
    }
    robots[n-1] = 0;
    robots[0] = 0; // 이걸 빼먹어서 틀림
}

🤖 주의점!! 

  • 먼저 컨베이어 벨트에 올라간 로봇이 먼저 내리므로, n-2부터 역순 탐색을 수행해야 한다. (질문게시판에 이 질문 많았다)
  • 그리고 다 한칸씩 자동으로 땡겨지는 거니까 맨 첫 칸은 0으로(로봇 없는걸로) 만들어줘야 한다! 이걸 빼먹어서 답이 자꾸 이상하게 나왔다;;

 

 

🤖 robotSelfMove() : 움직일 수 있는 로봇은 한 칸씩 걷기

static void robotSelfMove() {
    for (int i = n-2; i >= 0; i--) {
        if (robots[i] > 0) { // 로봇이 있는 칸
            if (robots[i+1] == 0 && first.get(i+1) >= 1) {
                robots[i+1] = robots[i];
                robots[i] = 0;
                int st = first.get(i+1);
                first.set(i+1, st - 1);
            }
        }
    }
    robots[n-1] = 0;
}
  • 로봇이 있는 칸인 경우, 다음칸에 로봇이 없고, 내구도가 1 이상인지 확인한다. 
    • 이 조건에 부합하면 옮겨주고, 원래 자리는 0으로 만든다.
    • 그리고 옮긴 후의 자리의 내구도는 -1해준다.
    • 마지막 칸에 도착한 로봇은 자동으로 내려준다(robots[n-1] = 0)

 

🤖 onRobot() 

static void onRobot() {
    int strength = first.get(0);
    if (strength > 0) {
        robots[0] = robotCount;
        first.set(0, strength-1);
    }

}
  • 첫 번째 칸 내구도가 0보다 크면 올려주기 

 

 

🤖 zeroCount() 

static int zeroCount() {
    int count = 0;
    count += (int) (first.stream().filter(o -> o== 0).count());
    count += (int) (second.stream().filter(o-> o == 0).count());
    return count;
}
  • first, second 각 리스트 돌면서 0인 칸의 개수를 세고 리턴. 

 


 

🤖 전체코드

import java.util.*;
import java.io.*;
public class p20055 {
    private static LinkedList<Integer> first;
    private static LinkedList<Integer> second;
    private static int[] robots;
    private static int n, k, robotCount;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        n = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());
        robotCount = 1;
        int step = 0;

        first = new LinkedList<>();
        second = new LinkedList<>();
        robots = new int[n];

        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < n; i++) {
            first.add(Integer.parseInt(st.nextToken()));
        }

        for (int i = n; i < 2*n; i++) {
            second.addFirst(Integer.parseInt(st.nextToken()));
        }


        while (zeroCount() < k) {
            rotateBelt();
            robotSelfMove();
            onRobot();
            step++;
        }
        System.out.println(step);
    }



    static void onRobot() {
        int strength = first.get(0);
        if (strength > 0) {
            robots[0] = robotCount;
            first.set(0, strength-1);
        }

    }

    static void rotateBelt() {
        int secondFirst = second.removeFirst();
        int firstLast = first.removeLast();

        first.addFirst(secondFirst);
        second.addLast(firstLast);

        // 첫 줄 마지막 칸 도착한 로봇은 내림
        for (int i = n-2; i >=0; i--) {
            robots[i+1] = robots[i];
        }
        robots[n-1] = 0;
        robots[0] = 0; // 이걸 빼먹어서 틀림
    }

    static void robotSelfMove() {
        for (int i = n-2; i >= 0; i--) {
            if (robots[i] > 0) { // 로봇이 있는 칸
                if (robots[i+1] == 0 && first.get(i+1) >= 1) {
                    robots[i+1] = robots[i];
                    robots[i] = 0;
                    int st = first.get(i+1);
                    first.set(i+1, st - 1);
                }
            }
        }
        robots[n-1] = 0;
    }

    static int zeroCount() {
        int count = 0;
        count += (int) (first.stream().filter(o -> o== 0).count());
        count += (int) (second.stream().filter(o-> o == 0).count());
        return count;
    }

}