[Python][백준] 20061번 모노미노도미노 2

신남·2022년 9월 28일

https://www.acmicpc.net/problem/20061

공부 날짜 : 2022.09.29
정답 참조 여부 : X

빨간색의 칸에 블록을 놓았을때 파란색과 초록색에 다른 방식으로 입력된다.
초록색과 파란색에서 테트리스의 룰을 따르며 0,1번 라인에 블록이 있으면 맨 아래쪽이 없어질때
블록 입력에 따라 점수와 남아있는 블록의 개수를 묻는 문제이다


꽤나 어려웠던 문제다.
테트리스 룰에의해 행 또는 열이 다 차게 되면 없어지는 경우에는 새로운 리스트에 담지 않는 방식으로 수를 낮춰가며 insert(0,value)로 표현했다.

그리고 그 후에 0,1번에 블록의 유무에 따라 pop(-1)을 수행하는 식으로 표현했는데
순서의 차이라던가 원본 데이터에서 따지느냐에 따라 많이 차이가 났다.


첫번째로 테트리스 룰에의해 줄을 삭제하는 경우 2~5까지만 해준뒤 0,1열을 따졌는데
이 경우에 줄이 삭제된뒤 0,1열에서 내려오는게 고려되지 않아 틀렸으며
0,1열의 데이터가 보존된 상태에서 0,1열을 따지기 때문에 블록이 지워지는 경우도 있었다.


두번째로 0,1열에서 range(1,-1,-1)로 반복하여 1번을 보고 0번을 봤다.
이 경우에 0,1번 둘다 블록이 있는경우 1번확인해서 pop(-1), insert(0,[0,0,0,0]) 해주게 되면 0번에서는 무조건 [0,0,0,0]이 되므로 순서를 바꿔 줘야 했다.


데이터를 보존해야하는지 지워야하는지, 혹은 어떤걸 먼저 체크하고 따질것인지 많은 생각을 해야하는 문제였다.

소스코드

import sys
from copy import deepcopy
input = sys.stdin.readline

n = int(input())

order = []

for _ in range(n):
    order.append(list(map(int, input().split())))
    
#################################
#블록 넣기
#밑에서 부터 y값에따라 블록을 넣음
#가로로 들어올 경우 low로 판단함
def put_block_to_green(y, low):
    global green
    input_layer = 0
    #가로로 들어오는 경우
    if low:
        for layer in range(7):
            if layer == 6 or green[layer][y] == 1 or green[layer][y+1] == 1:
                green[layer-1][y] = 1
                green[layer-1][y+1] = 1
                break
                
    #한칸만 들어오는 경우
    else:
        for layer in range(7):
            #블록이 없으면 블록을 넣고 스탑
            if layer == 6 or green[layer][y] == 1:
                green[layer-1][y] = 1
                break

#파란색    
def put_block_to_blue(x, low):
    global blue
    if low:
        for layer in range(7):
            if layer == 6 or blue[layer][x] == 1 or blue[layer][x+1] == 1:
                blue[layer-1][x] = 1
                blue[layer-1][x+1] = 1
                break
            

    else:                
        for layer in range(7):
            if layer == 6 or blue[layer][x] == 1:
                blue[layer-1][x] = 1
                break

            
#블록과 x,y를 넣어주면 값을 바꿔서 초록 파랑에 블록을 넣어줌
#세로로 들어오는 경우는 한칸으로 2번 들어가는 식으로 판단
def put_block(block,x,y):
    if block == 1:
        put_block_to_green(y,False)
        put_block_to_blue(x,False)
        
    elif block == 2:
        put_block_to_green(y,True)
        put_block_to_blue(x,False)
        put_block_to_blue(x,False)
        
    elif block == 3:
        put_block_to_green(y,False)
        put_block_to_green(y,False)
        put_block_to_blue(x,True)
        
######################################

######################################
#가득 찼는지 와 0,1라인에 블록 있는지 체크
def check():
    global reward, green, blue
    #blue와 green을 보존하고 새로 담을 변수
    new_blue = []
    new_green = []
    
    #맨밑(5)에서 0까지 체크하면서 올라감
    for i in range(5,-1,-1):
        blue_check = True
        green_check = True
        #칸중에 0이있으면 그대로 담음
        for j in range(4):
            if green[i][j] == 0:
                green_check = False
            if blue[i][j] == 0:
                blue_check = False
                
        #0이 있으면 그대로 담아줌
        #0이 없으면(1로 가득 찼으면) 점수 1점 추가
        if blue_check == False:
            new_blue.insert(0, deepcopy(blue[i]))
        else:
            reward += 1
            
        if green_check == False:
            new_green.insert(0, deepcopy(green[i]))
        else:
            reward += 1
            
    #블록을 채운뒤 6x4의 행렬을 만들기 위해 [0,0,0,0]을 채워줌        
    for _ in range(len(new_blue), 6):
        new_blue.insert(0, [0,0,0,0])
        
    for _ in range(len(new_green), 6):
        new_green.insert(0, [0,0,0,0])
        
        
    blue = deepcopy(new_blue)
    green = deepcopy(new_green)
    
    #0과 1에 블록이 있는지 체크
    for i in range(2):
        blue_check = False
        green_check = False
        for j in range(4):
            #블록이 있으면 맨밑에 없애고 그 칸을 맨위에 추가
            if green[i][j] == 1:
                green_check = True
                
            if blue[i][j] == 1:
                blue_check = True
                
        
        if green_check:
            green.pop(-1)
            green.insert(0,[0,0,0,0])
        if blue_check:
            blue.pop(-1)
            blue.insert(0,[0,0,0,0])
            
            
            
            
######################################
blue = [[0 for _ in range(4)] for _ in range(6)]
green = [[0 for _ in range(4)] for _ in range(6)]    

reward = 0

while order:
    block,x,y = order.pop(0)
    
    put_block(block,x,y)
    check()

    
    
result = 0
for i in range(6):
    for j in range(4):
        if blue[i][j] == 1:
            result += 1
        if green[i][j] == 1:
            result += 1
            
print(reward)
print(result)

0개의 댓글