알고리즘/구현 & 그리디 & 브루트포스

[백준]JAVA - 20055번: 컨베이어 벨트 위의 로봇

K.두부 2022. 12. 14. 00:34
반응형

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

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

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

www.acmicpc.net

풀이

문제의 조건 및 구동 순서는 아래와 같다.
1. 벨트가 각 칸 위에 있는 로봇과 함께 움직인다.
2. 가장 먼저 벨트에 올라간 로봇부터 회전 방향으로 한 칸씩 이동한다. (이동하려는 칸의 내구도가 0 이상이며 로봇이 없을 경우)
3. 올리는 위치에 있는 칸의 내구도가 0이 아니면 로봇을 올릴 수 있다.
4. 위의 과정을 내구도가 0인 칸의 개수가 K개 이상일 때까지 반복한다.

처음 문제를 읽었을 때 필자는 도통 무슨 말인지 이해할 수 없었다. 한참을 고민하다가 해답을 보고서야 문제를 이해할 수 있었는데 예제 1번을 통해서 살펴보겠다.

time = 1
1. 벨트가 각 칸 위에 있는 로봇과 함께 움직인다. (현재 벨트 위에 올라간 로봇이 없으므로 벨트만 움직임)

2. 가장 먼저 벨트에 올라간 로봇부터 벨트의 회전 방향으로 이동 (현재 벨트 위에 올라간 로봇이 없으므로 패스)
3. 올라가는 위치에 로봇이 없고, 내구도가 1 이상이면 로봇을 올린다.

4. 내구도가 0인 칸이 K(2)개 이하이므로 위 과정을 반복한다.

time = 2
1. 벨트가 각 칸 위에 있는 로봇과 함께 움직인다.

2. 가장 먼저 벨트에 올라간 로봇부터 벨트의 회전 방향으로 이동
2-1. 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없고, 내구도가 1 이상 이어야 한다.
본문. 로봇이 내려가는 위치에 도달하면 즉시 로봇을 내린다.
∴ 로봇을 옮기고, 내려가는 위치에 도달했기 때문에 즉시 내려감

3. 올라가는 위치에 로봇이 없다면 로봇을 올린다. (내구도가 1 이상 이어야 함)

4. 내구도 0인 칸이 K(2) 개 이상이기 때문에 위 과정을 종료한다.

정답은 2.
예제 1번을 그림으로 과정을 살펴보았다. 이제 이해가 됐을 거라고 생각한다.
1차원 배열로 입력값을 주었고, 올라가는 위치, 내려가는 위치에 대한 상세한 내용이 없어서 문제를 읽은 직후에 이해가 많이 어려웠다.

문제를 이해했다면 해결하는 건 쉽다.
컨베이어 벨트는 1차원 배열로도 충분히 해결할 수 있기 때문에 1차원 배열로 map 배열을 생성했다.
로봇은 벨트 위에 존재 유무만 판단하면 되기 때문에 boolean 형태로 생성했다.

1단계. 벨트가 각 칸 위에 있는 로봇과 함께 움직인다.

public static void TurnBelt(int tmp) {
    for (int i=A.length-1; i>0; i--) {
        A[i] = A[i-1];
    }
		
    for (int i=robot.length-1; i>0; i--) {
        robot[i] = robot[i-1];
    }
		
    A[0] = tmp;
    robot[0] = false;
    
    // 로봇이 내려가는 곳에 도달했을 경우 즉시 내림
    if (robot[N-1] == true) robot[N-1] = false;
}

이동시켜야 할 때 주의할 점은 뒤에서부터 값을 변경해주어야 한다. 앞에서부터 변경하게 되면 코드가 굉장히 어려워진다. 또한, 첫 번째 값을 변경해주는 걸 잊지 말자.

2. 가장 먼저 벨트에 올라간 로봇부터 벨트의 회전 방향으로 이동

public static void TurnRobot() {
    for (int i=robot.length-1; i>0; i--) {
    
        // 로봇이 한 칸 이동할 수 있을 경우
        if (robot[i-1] == true && robot[i] == false && A[i] > 0) {
            robot[i] = robot[i-1];
            robot[i-1] = false;
				
            A[i]--;
            if  (A[i] == 0) K--;
        }
    }
		
    robot[0] = false;
    
    //  로봇이 내려가는 곳에 도달했을 경우 즉시 내림
    if (robot[N-1] == true) robot[N-1] = false;
}

로봇이 이동할 수 있는 곳을 찾은 후에 변경해주면 된다. 로봇이 이동한 자리는 초기화해주는 걸 잊지말자. 또한, 이동했다면 내구도를 1 감소시키고, 0이 됐다면 K를 마이너스해준다.

<최종코드>

import java.io.*;
import java.util.*;

public class Main {
    static int[] A;
    static boolean[] robot;
    static int N, K, time = 0;
    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());
		
        A = new int[2*N];
        robot = new boolean[N];
		
        st = new StringTokenizer(br.readLine());
        for (int i=0; i<A.length; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }
		
        while (K > 0) {
            time++;
			
            TurnBelt(A[2*N-1]); // 1. 벨트 한 칸 회전
            TurnRobot(); // 2. 로봇 이동
			
            // 3. 로봇 출발선에 올림
            if (robot[0] == false && A[0] > 0) {
                robot[0] = true;
                A[0]--;
				
                if (A[0] == 0) K--;
            }
        }
		
        System.out.println(time);
    }
	
    public static void TurnBelt(int tmp) {
        for (int i=A.length-1; i>0; i--) {
            A[i] = A[i-1];
        }
		
        for (int i=robot.length-1; i>0; i--) {
            robot[i] = robot[i-1];
        }
		
        A[0] = tmp;
        robot[0] = false;
		
        // 로봇이 내려가는 곳에 도달했을 경우 즉시 내림
        if (robot[N-1] == true) robot[N-1] = false;
    }
	
    public static void TurnRobot() {
        for (int i=robot.length-1; i>0; i--) {
            
            // 로봇이 한 칸 이동할 수 있을 경우
            if (robot[i-1] == true && robot[i] == false && A[i] > 0) {
                robot[i] = robot[i-1];
                robot[i-1] = false;
				
                A[i]--;
                if  (A[i] == 0) K--;
            }
        }
		
        robot[0] = false;
        
        //  로봇이 내려가는 곳에 도달했을 경우 즉시 내림
        if (robot[N-1] == true) robot[N-1] = false;
    }
}
반응형