파이썬 박스(백준 BOJ 9455)


문제

m행 n열로 이루어진 그리드가 주어진다. 일부 칸에는 박스가 들어 있다. 모든 박스가 더 이상 움직일 수 없을 때 까지 아래로 움직인다면, 박스는 쌓여진 상태가 된다.

그림 (a)의 그리드의 크기는 5행 4열이고, 7칸에는 박스가 들어있다. 모든 박스가 계속해서 아래로 움직이면, 그림 (b)와 같이 변하게 된다.

img

박스가 움직인 거리는 바닥에 쌓이기 전 까지 이동한 칸의 개수이다. 예를 들어, 맨 왼쪽 열에서 가장 위에 있는 박스가 움직인 거리는 2이다. 모든 박스가 이동한 거리 (각 박스가 이동한 거리의 합) 을 구하는 프로그램을 작성하시오. 위의 예제에서 박스 7개가 움직인 거리는 8이다.


입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 m과 n이 주어진다. (1 ≤ m, n ≤ 100) 다음 m개 줄에는 그리드의 각 행의 정보를 나타내는 n개의 정수가 주어진다. 그리드 첫 행부터 마지막 행까지 순서대로 주어진다. 박스가 들어있는 칸은 1로, 다른 칸은 0으로 주어진다. 각 정수 사이에는 공백이 하나 주어진다.


출력

각 테스트 케이스마다 입력으로 주어진 그리드에서 모든 박스가 이동한 거리를 출력한다.


예제 입력 1

3
5 4
1 0 0 0
0 0 1 0
1 0 0 1
0 1 0 0
1 0 1 0
3 3
1 1 1
1 1 1
0 0 0
5 6
1 0 1 1 0 1
0 0 0 0 0 0
1 1 1 0 0 0
0 0 0 1 1 1
0 1 0 1 0 1

예제 출력 1

8
6
16


📝 풀어보기

📌 이 문제에는 크게 3가지의 조건이 있다.

  1. 현재 박스 아래에는 박스가 없어야 한다.
  2. 박스는 바닥을 벗어나면 안된다. -> 리스트의 범위를 벗어나면 안된다.
  3. 박스를 이동할 때에는 현재 위치는 0으로 저장되고 아래 위치는 1로 저장한다.


📌 먼저 테스트 케이스를 입력받고 T만큼 반복하면서 N, M (행과 열)을 입력받는다.

그리고 박스들의 움직임을 표현할 2차원 리스트를 생성하고 박스가 있는 공간, 빈 공간, 움직임을 확인할 수 있게 변수를 생성한다.

T = int(input())

for _ in range(T):
    N, M = map(int, input().split()) # N 행 M 열
    box_list = [list(map(int, input().split())) for _ in range(N)] 
    box = 1
    empty = 0
    move = 0


📌 열과 행의 역순(아래에서 위로)을 탐색하며 탐색중인 좌표에 박스가 있으면 조건에 따른 실행을 하도록 한다.

그리고 박스가 있던 위치를 0으로 바꾸고 박스가 아래로 이동했으므로 이동한 자리는 1로 변경한다. break될 때 까지 y를 증가시키면서 이동값을 누적하고 출력한다.

   # 2중 반복문
    # 열부터 순환
    for x in range(M): # 열(row) 개수
        # 행순회, 단 아래에서 위로 탐색을 한다.
        for y in range(N-1,-1,-1): # 4 3 2 1 0
            
            # 만약에 현재 탐색하고 있는 좌표에 박스가 있으면
            if box_list[y][x] == box:
                while True:
                    # 조건1. 현재 박스 아래에 박스가 없어야 한다.
                    if y+1 == N:
                        break
                    # 조건2. 박스가 바닥을 벗어나면 안된다.
                    if box_list[y+1][x] == box:
                        break
                
                    box_list[y][x] = empty
                    box_list[y+1][x] = box
                    y += 1
                    move += 1

    print(move)


전체 코드

# 1. 현재 박스 아래에 박스가 없어야 한다.
# 2. 박스는 바닥을 벗어나면 안된다. -> 리스트의 범위를 벗어나면 안된다.
# 3. 박스이동 -> 현재 위치는 0 저장, 아래 위치는 1 저장


T = int(input())

for _ in range(T):
    N, M = map(int, input().split()) # N 행 M 열
    box_list = [list(map(int, input().split())) for _ in range(N)] 
    box = 1
    empty = 0
    move = 0

    # 2중 반복문
    # 열부터 순환
    for x in range(M): # 열(row) 개수
        # 행순회, 단 아래에서 위로 탐색을 한다.
        for y in range(N-1,-1,-1): # 4 3 2 1 0
            
            # 만약에 현재 탐색하고 있는 좌표에 박스가 있으면
            if box_list[y][x] == box:
                while True:
                    # 조건1. 현재 박스 아래에 박스가 없어야 한다.
                    if y+1 == N:
                        break
                    # 조건2. 박스가 바닥을 벗어나면 안된다.
                    if box_list[y+1][x] == box:
                        break
                
                    box_list[y][x] = empty
                    box_list[y+1][x] = box
                    y += 1
                    move += 1

    print(move)


관심있을 포스팅