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)