https://www.acmicpc.net/problem/20055
키워드
로봇은 올리는 위치에만 올릴 수 있다.
언제든지 로봇이 내리는 위치에 도달하면 그 즉시 내린다.
로봇은 컨베이어 벨트 위에서 스스로 이동할 수 있다.
로봇을 올리는 위치에 올리거나 로봇이 어떤 칸으로 이동하면 그 칸의 내구도는 즉시 1만큼 감소한다.
- 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
- 가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
- 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.
- 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
- 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다. 그렇지 않다면 1번으로 돌아간다.
종료되었을 때 몇 번째 단계가 진행 중이었는지 구해보자. 가장 처음 수행되는 단계는 1번째 단계이다.
구현
- 각 단계를 메소드로 분리하여 구현하면 간단하게 풀린다.
- 내구도가 0인 컨베이어 칸의 수를 저장하는 변수를 생성한다.
- 로봇 ArrayList와 컨베이어 벨트 1차원 배열을 생성한다.
- **로봇 객체**는 현재 **컨베이어 번호**를 가진다.
- **컨베이어 벨트 객체**는 **현재 위치에 로봇이 있는지**에 대한 정보와 내구도 정보를 가진다.
- 벨트를 회전시키는 메소드 구현
- [i] → [(i+1) % 2N]
- 로봇 배열도 인덱스를 위와 같이 증가시킨다.
- 로봇이 내릴 수 있으면 내린다.
- 로봇을 한 칸 이동시키는 메소드 구현
- 로봇 배열의 맨 앞부터 이동할 수 있으면 이동한다.
- 이동하려는 위치의 컨베이어벨트 내구도를 1감소시킨다.
- 0이라면 칸의 수를 저장하는 변수 +1을 한다.
- 이동하려는 위치의 컨베이어벨트 내구도를 1감소시킨다.
- 로봇이 내릴 수 있으면 내린다.
- 로봇 배열의 맨 앞부터 이동할 수 있으면 이동한다.
- 로봇을 올리는 메소드 구현
- [0] 인덱스에 로봇이 없고, 내구도가 1 이상이라면 로봇을 올린다.
- [0] 위치의 컨베이어 칸의 내구도를 1감소시킨다.
- 0이라면 칸의 수를 저장하는 변수 +1을 한다.
- [0] 위치의 컨베이어 칸의 내구도를 1감소시킨다.
- [0] 인덱스에 로봇이 없고, 내구도가 1 이상이라면 로봇을 올린다.
- 내구도가 0인 칸의 갯수 판단하여 종료하는 메소드 구현
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.function.Predicate;
public class java_20055 {
static int N, K;
static Belt beltList[];
static List<Robot> robotList;
static int beltCount;
static class Belt {
boolean robot;
int durability;
public Belt(int durability) {
this.robot = false;
this.durability = durability;
}
}
static class Robot {
int index;
public Robot() {
this.index = 0;
}
}
static void beltMove() {
// 벨트 회전하기
Belt tmp = beltList[2 * N - 1];
for (int i = 2 * N - 1; i > 0; i--) {
beltList[i] = beltList[i - 1];
}
beltList[0] = tmp;
// 로봇도 같이 회전하기
for (Robot robot : robotList) {
robot.index = (robot.index + 1) % (2 * N);
// 로봇의 현재 위치가 N-1 이라면 내리기
if (robot.index == N - 1) {
beltList[N - 1].robot = false;
}
}
// 로봇 내리기
robotList.removeIf(new Predicate<Robot>() {
@Override
public boolean test(Robot t) {
if (t.index == N - 1) {
return true;
}
return false;
}
});
}
static void robotMove() {
// 로봇 이동하기
for (int i = 0; i < robotList.size(); i++) {
// 이동할 인덱스
int moveIndex = (robotList.get(i).index + 1) % (2 * N);
// 벨트의 내구도가 1 이상 이여야 하며
if (1 <= beltList[moveIndex].durability) {
// 그 위치에 로봇이 없어야 한다.
if (!beltList[moveIndex].robot) {
// 현재 위치 로봇 없어짐
beltList[robotList.get(i).index].robot = false;
// 이동할 위치 로봇 생김
beltList[moveIndex].robot = true;
// 내구도 감소
beltList[moveIndex].durability -= 1;
// 로봇의 위치 조정
robotList.get(i).index = moveIndex;
// 내구도가 0이 된다면.. 0카운트 증가
if (beltList[moveIndex].durability == 0) {
beltCount++;
}
// 현재 인덱스가 N-1 이라면.. 로봇 내리기
if (moveIndex == N - 1) {
beltList[moveIndex].robot = false;
}
}
}
}
// 로봇 내리기
robotList.removeIf(new Predicate<Robot>() {
@Override
public boolean test(Robot t) {
if (t.index == N - 1) {
return true;
}
return false;
}
});
}
public static void loadRobot() {
// 로봇 올리기
// 내구도가 1 이상이여야 함
if (1 <= beltList[0].durability) {
// 로봇이 없어야 함
if (!beltList[0].robot) {
// 로봇 올라감
beltList[0].robot = true;
robotList.add(new Robot());
// 내구도 감소
beltList[0].durability -= 1;
// 내구도가 0이 된다면.. 0카운트 증가
if (beltList[0].durability == 0) {
beltCount++;
}
}
}
}
public static boolean stopCheck() {
// 내구도가 0인 칸의 갯수가 K개 이상이면 .. 종료
if (K <= beltCount) {
return true;
}
return false;
}
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());
beltList = new Belt[2 * N];
st = new StringTokenizer(br.readLine());
// 내구도가 0인 벨트의 수
beltCount = 0;
for (int i = 0; i < 2 * N; i++) {
beltList[i] = new Belt(Integer.parseInt(st.nextToken()));
if (beltList[i].durability == 0) {
beltCount++;
}
}
// 로봇 리스트 생성
robotList = new ArrayList<>();
int round = 1;
while (true) {
beltMove();
robotMove();
loadRobot();
if (stopCheck()) {
break;
} else {
// 단계 증가
round++;
}
}
System.out.println(round);
br.close();
}
}
'Coding Test > BOJ' 카테고리의 다른 글
[BOJ/JAVA] 11725번: 트리의 부모 찾기 (0) | 2022.11.14 |
---|---|
[BOJ/JAVA] 11559번: Puyo Puyo (0) | 2022.11.07 |
[BOJ/JAVA] 14653번: 너의 이름은 (0) | 2022.11.07 |
[BOJ/JAVA] 1063번: 킹 (0) | 2022.11.07 |
[BOJ/JAVA] 20058번: 마법사 상어와 파이어스톰 (0) | 2022.11.07 |