티스토리 뷰

https://www.acmicpc.net/problem/20055
20055번: 컨베이어 벨트 위의 로봇
길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부��
www.acmicpc.net
난이도 : 실버 1
문제 이해를 못해서 지문을 몇 번 읽었는지 모르겠습니다.
제가 헷갈렸던 부분을 위주로 설명하겠습니다.

이 그림을 처음에 컨베이어 벨트를 위에서 바라본 모습으로 착각했네요.

이런 형식의 그림으로 착각해서 시작부터 꼬였습니다.

이런 식으로 컨베이어 벨트를 옆에서 바라본 것으로 생각하면 이해하기 쉽습니다.
위 그림의 경우 1~5가 상단에 위치하고 있고 1이 올라가는 위치, 5가 내려가는 위치입니다. 즉, 로봇이 5에 위치하면 로봇이 내려갑니다. 5번에서 로봇이 이동하거나 벨트가 회전하여 떨어지는 구조가 아닙니다. 이 조건 때문에 몇 시간을 버렸는지 모르겠네요.
저는 2*n 크기의 배열을 통해 풀었습니다. 다양한 방법이 있겠지만 left와 right를 이용하여 원형 큐처럼 시작과 끝이 연결된 배열을 모델로 했습니다. 로봇이 있는 n 크기의 배열까지 총 2개의 배열을 이용하여 풀었습니다.
1. 벨트가 한 칸 회전한다.
=> left와 right를 1씩 감소시켜줍니다. 벨트는 시계 방향으로 회전합니다. 또, 벨트가 회전했을 시 로봇의 위치도 우측으로 이동하게 되므로 모든 로봇들을 내구도 감소 없이 우측으로 1칸씩 이동시켜줍니다.
2. 로봇이 한 칸 이동한다.
=> 로봇배열과 벨트 배열의 조건을 잘 비교합니다. 로봇 배열에서 이동할 위치는 비어있어야 하며, 벨트 배열에서 이동할 위치의 내구도가 1 이상인지 확인합니다.
3. 로봇을 올린다.
=> left 인덱스의 로봇, 벨트 배열을 확인 후 로봇을 올립니다.
모든 과정 중 내구도가 0인 칸이 생긴다면 k의 값을 1씩 감소시켰습니다. 물론 새로운 변수를 만들어 이 값을 증가시키고 k와 비교해도 무방합니다.
전역 변수
int n, k = 문제에서 주어진 입력(크기, 빈 칸 개수)
int map[] = 벨트의 내구도
int left, right = 벨트 배열에서 인덱스를 가리키는 변수
boolean robot[] = 로봇이 존재하는지 저장하는 배열
메소드
void main
입력을 받고 k가 0 이하로 될 때까지 while문을 반복합니다. 한 바퀴는 count의 증가, 벨트의 회전, 로봇의 이동, 새 로봇 추가의 동작이 있습니다.
(moveBelt, moveRobot, newRobot 호출)
void moveBelt
left, right의 값을 1씩 감소시킵니다. 원형 구조이므로 -1의 값이 된다면 2*n-1(우측)으로 이동시킵니다.
벨트가 회전하면 로봇도 이동해야 하므로 우측으로 1칸씩 당겨줍니다. 내구도 소모는 없습니다.
void moveRobot
로봇이 우측으로 이동할 수 있다면 이동합니다. 단, 우측에 내구도가 있으며 로봇이 있으면 안 됩니다. 로봇이 이동했다면 내구도를 1 감소시키고 0이 됐다면 k의 값을 1 감소시킵니다.
void newRobot
벨트의 시작 부분(left)에 새 로봇을 놓습니다. 로봇이 놓였다면 내구도를 1 감소시킵니다.
import java.io.BufferedReader; | |
import java.io.InputStreamReader; | |
import java.util.StringTokenizer; | |
public class p20055 { | |
static int n, k, map[], left, right; | |
static boolean robot[]; | |
public static void main(String[] args) throws Exception { | |
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | |
StringTokenizer stz = new StringTokenizer(br.readLine()); | |
n = Integer.parseInt(stz.nextToken()); | |
k = Integer.parseInt(stz.nextToken()); | |
map = new int[2*n]; | |
robot = new boolean[n]; | |
stz = new StringTokenizer(br.readLine()); | |
for(int i = 0; i < 2* n; i++) | |
map[i] = Integer.parseInt(stz.nextToken()); | |
left = 0; | |
right = n; | |
int count = 0; | |
while(k > 0) { | |
count++; | |
moveBelt(); | |
moveRobot(); | |
newRobot(); | |
} | |
System.out.println(count); | |
} | |
public static void moveBelt() { | |
left--; | |
right--; | |
if(left == -1) | |
left = 2*n-1; | |
if(right == -1) | |
right = 2*n-1; | |
for(int i = n-2; i >= 0; i--) { | |
if(robot[i]) { | |
robot[i] = false; | |
if(i+1 < n-1) | |
robot[i+1] = true; | |
} | |
} | |
} | |
public static void moveRobot() { | |
for(int i = n-2; i >= 0; i--) { | |
if(robot[i]) { | |
int next = left+i+1; | |
if(next >= 2*n) | |
next -= 2*n; | |
if(!robot[i+1] && map[next] >= 1) { | |
robot[i] = false; | |
if(i+1 < n-1) | |
robot[i + 1] = true; | |
map[next]--; | |
if(map[next] == 0) | |
k--; | |
} | |
} | |
} | |
} | |
public static void newRobot() { | |
if(!robot[0] && map[left] > 0) { | |
robot[0] = true; | |
map[left]--; | |
if(map[left] == 0) | |
k--; | |
} | |
} | |
} |
'문제풀이 > 백준 && 프로그래머스' 카테고리의 다른 글
[백준 20057] 마법사 상어와 토네이도 (자바) (0) | 2020.10.21 |
---|---|
[백준 20056] 마법사 상어와 파이어볼 (자바) (3) | 2020.10.21 |
[백준 17081] RPG Extreme (자바) (2) | 2020.10.19 |
[백준 2146] 다리 만들기 (자바) (0) | 2020.10.16 |
[백준 1766] 문제집 (자바) (0) | 2020.10.16 |