It's easy, if you try

[백준/boj] 20055: 컨베이어 벨트 위의 로봇 (Java) / 구현 / 시뮬레이션 본문

알고리즘/자바(Java)

[백준/boj] 20055: 컨베이어 벨트 위의 로봇 (Java) / 구현 / 시뮬레이션

s5he2 2021. 2. 23. 23:30
반응형

문제

 

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

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

www.acmicpc.net

풀이

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

public class Main {
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
	static int N, K;
	static Belt[] belt;

	private static class Belt {
		int power;
		boolean isRobotHere;

		Belt(int power, boolean isRobotHere) {
			this.power = power;
			this.isRobotHere = isRobotHere;
		}
	}

	public static void main(String[] args) throws Exception {
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		st = new StringTokenizer(br.readLine());
		belt = new Belt[N * 2];
		for (int i = 0; i < N * 2; i++) {
			belt[i] = new Belt(Integer.parseInt(st.nextToken()), false);
		}

		System.out.println(move());
	}

	private static int move() {
		int Dan = 0;
		while (true) {
			Dan++;
			rotate(); 
			moveRobot();
			robotStart();
			if (isK()) {
				break;
			}
		}
		return Dan;
	}

	private static boolean isK() {
		int count = 0;
		for (int i = 0; i < N * 2; i++) {
			if (belt[i].power == 0) {
				count++;
			}
		}
		return count >= K ? true : false;
	}

	private static void robotStart() {
		if (!belt[0].isRobotHere && belt[0].power > 0) {
			belt[0].power--;
			belt[0].isRobotHere = true;
		}
	}

	private static void moveRobot() {
		for (int i = N - 2; i >= 0; i--) {
			if (belt[i].isRobotHere) {
				if (i + 1 == N-1) {
					if (belt[i + 1].power > 0) {
						belt[i].isRobotHere = false;
						belt[i+1].power--;
						continue;
					}
				}
				if (belt[i + 1].isRobotHere || belt[i + 1].power == 0)
					continue;
				belt[i + 1].isRobotHere = true;
				belt[i + 1].power--;
				belt[i].isRobotHere = false;
			}
		}
	}

	private static void rotate() {
		boolean isRobotTemp = belt[2 * N - 1].isRobotHere;
		int powerTemp = belt[2 * N - 1].power;
		for (int i = N * 2 - 1; i >= 1; i--) {
			belt[i].isRobotHere = belt[i - 1].isRobotHere;
			belt[i].power = belt[i - 1].power;
			if (i == N - 1) {
				belt[i].isRobotHere = false;
			}
		}
		belt[0].isRobotHere = isRobotTemp;
		belt[0].power = powerTemp;
	}
}

Belt 클래스

  • 내구도(power: int)와 로봇이 올려져있는 여부(isRobotHere : boolean)를 가지고 있다.

Belt[] belt

  • 컨테이너 벨트의 상태를 배열로 표현했다. (Belt[] belt)
  • 길이는 2N이다. (인덱스 0 부터 인덱스 2N-1)
    • 때문에 올라가는 위치는 0, 내려가는 위치는 N-1이다.

rotate

1. 벨트가 한 칸 회전한다.

에 해당하는 함수이다.

1. 벨트가 회전하는 것을 구현하기 위해 마지막 배열 값을 temp로 두고,

2. 뒤에서부터 바로 앞의 값을 자신에게 할당해 가는 식으로 오른쪽으로 한칸씩 이동 시켰다.

3. 마지막에 temp값을 belt[0]에 할당 시켰다. 

배열의 경우 얕은 복사(한쪽의 값을 바꾸면 동시에 바뀌는 것)를 주의 해야하기 때문에 power, isRobotHere 값 하나하나를 할당해줬다.

moveRobot

2.가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
  1. 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.

에 해당하는 함수이다.

먼저 로봇은 내려가는 위치(N-1)에서 반드시 내려가기 때문에 N-1(내려가는 위치 인덱스)에서부터 N*2-1 (마지막 인덱스)까지는 로봇이 없다. 또한, 먼저 올라온 로봇부터 오른쪽으로 한칸씩 이동하기 때문에 for문을 N-2 부터 0까지 즉, 가장 오른쪽 칸부터 살펴봤다.

1. 만약 현재 칸에 로봇이 있다면

  • 먼저, 그 다음(오른쪽)(i+1)칸이 내려가는 위치(N-1)인지 확인한다. 내려가는 위치라면 i+1 번째 칸의 내구도(power)를 하나 감소시키면서 내려가면 된다(belt[i+1].isRobotHere = false); 내려간 후에는 continue를 통해 다음 왼쪽칸을 살펴본다.
  • 그 다음 칸이 내려가는 위치가 아니라면, 이번엔 다음칸에 로봇이 있는지 또는 내구도가 0인지를 확인한다. 둘 중 하나라도 해당된다면 이동할 수 없으므로 continue를 통해 다음 칸을 살펴본다.
  • 그 다음 칸이 위 두가지 조건에 모두 해당하지 않는다면, 로봇이 이동할 수 있음을 의미한다. 다음 칸의 내구도를 하나 감소시키고, isRobotHere를 true로 바꿔준다. 그리고 현재 칸의 isRobotHere는 false로 바꿔준다.

2. 현재 칸에 로봇이 없다면 다음 왼쪽 칸을 살펴본다.

robotStart

3. 올라가는 위치에 로봇이 없다면 로봇을 하나 올린다.

에 해당하는 함수이다.

간단하게 belt[0] 즉, 첫번째 칸에 로봇이 있는지 그리고 내구도는 0보다 높은지 확인한후 두가지를 모두 만족하면 첫번째 칸의 내구도를 하나 다운시키면서 올라간다(belt[0].isRobotHere = true).

isK

4. 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다. 그렇지 않다면 1번으로 돌아간다.

에 해당하는 함수이다. 원래 내구도(power)를 내릴때마다 확인해주는 것도 방법이지만

반응형
Comments