-
백준 20055Java/코딩테스트 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; } }