728x90

백준 20055_컨베이어 벨트 위의 로봇

시간 제한 1초, 메모리 제한 512MB

# 조건

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

  • 벨트가 한 칸 회전하면 1번부터 2N-1번까지의 칸은 다음 번호의 칸이 있는 위치로 이동하고, 2N번 칸은 1번 칸의 위치로 이동한다.
  • i번 칸의 내구도는 Ai이다.
  • 위의 그림에서 1번 칸이 있는 위치를 "올리는 위치", N번 칸이 있는 위치를 "내리는 위치"라고 한다.
  • 컨베이어 벨트에 박스 모양 로봇을 하나씩 올리려고 한다.
  • 로봇은 올리는 위치에만 올릴 수 있다.
  • 언제든지 로봇이 내리는 위치에 도달하면 그 즉시 내린다.
  • 로봇은 컨베이어 벨트 위에서 스스로 이동할 수 있다.
  • 로봇을 올리는 위치에 올리거나 로봇이 어떤 칸으로 이동하면 그 칸의 내구도는 즉시 1만큼 감소한다.
  • 컨베이어 벨트를 이용해 로봇들을 건너편으로 옮기려고 한다. 로봇을 옮기는 과정에서는 아래와 같은 일이 순서대로 일어난다.
    1. 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
    2. 가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
    3. 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.
    4. 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
    5. 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다. 그렇지 않다면 1번으로 돌아간다.
  • 종료되었을 때 몇 번째 단계가 진행 중이었는지 구해보자. 가장 처음 수행되는 단계는 1번째 단계이다.

입력

  • 첫째 줄에 N, K가 주어진다.
  • 둘째 줄에는 A1, A2, ..., A2N이 주어진다.

출력

  • 몇 번째 단계가 진행 중일 때 종료되었는지 출력한다.

# 접근 방법

  • 시뮬레이션 문제는 주어진 조건을 잘 정리해서 그대로 함수화하여 구현 해주면 된다.
    • 처음에 조건 정리해서 의사코드 짜는 것이 제일 중요한 듯..!
  • 헷갈리지 말아야 할 것이, 벨트가 함께 회전하므로 내구도를 기록해준 리스트도 함께 회전하여야 한다.
    • 가장 처음 수행되는 단계는 1번이므로 주의하여야 한다.
    • 로봇 이동시 0번 자리는 0으로 없다고 변경해주어야 한다.
  • 로봇 스스로 이동은 가장 먼저 올린 로봇부터 체크해주어야 하므로 리스트 뒤에서부터 체크한다.
    • 내리는 위치는 내구도와 상관없이 로봇을 내리므로 주의해주어야 한다.
  • 몇 번째 단계가 진행 중인지 체크하기 위하여 CNT 변수를 사용해준다.
    • 1, 2, 3, 4번까지 완료된 후 cnt += 1
  • 또한 종료 조건은 내구도가 0인 칸의 개수가 K개 이상일 때이므로, 0의 내구도가 발생한다면 실시간으로 체크해준다.
import sys  
sys.stdin = open('input.txt')  
input = sys.stdin.readline  

# 로봇과 벨트 함께 회전  
def rotate_with_robot():  
    # 벨트 회전  
    # 마지막 내구도 저장해준 후 1 ~ 마지막을 0 ~ 마지막 앞에까지로 복사해준다.    
    l_belt = belt[-1]  
    belt[1:] = belt[0:2*N-1]  
    belt[0] = l_belt  

    # 로봇은 1 ~ 마지막을 0~마지막 앞 까지만 복사해주면 된다.  
    robots[1:] = robots[0:N-1]  
    robots[0] = 0  

# 로봇 스스로 이동  
def robot_move():  
    # 가장 먼저 올라간 로봇이 이동해야되므로 뒤에서부터 체크  
    for i in range(N-1, -1, -1):  
        if robots[i]:  
            # 로봇이 내리는 위치라면 내리고  
            if i == N-1:  
                robots[i] = 0  
            else:  
                # 내리는 위치가 아니라면 로봇이 없고, 벨트 내구도가 0보다 많다면 이동  
                # 이동 후에는 내구도를 -1 해주어야 한다.                
                if not robots[i+1] and belt[i+1]:  
                    robots[i] = 0  
                    robots[i+1] = 1  
                    belt[i+1] -= 1  
# 로봇 올리기  
def raise_robot():  
    if belt[0]:  
        robots[0] = 1  
        belt[0] -= 1  


N, K = map(int, input().split())  
belt = [*map(int, input().split())]  

robots = [0]*N  
cnt = 0  
zero_cnt = belt.count(0)  

# 내구도가 0개 이하일 때까지 반복문 진행한다.  
while zero_cnt < K:  
    cnt += 1  
    # 로봇과 벨트 함께 회전  
    rotate_with_robot()  

    # 로봇 스스로 이동  
    robot_move()  

    #올리는 위치의 내구도가 0이 아니라면 로봇 올려주기  
    raise_robot()  

    zero_cnt = belt.count(0)  

print(cnt)
728x90