문제
https://www.acmicpc.net/problem/19235
접근
- 문제에 주어진 대로 구현하면 되는 시뮬레이션 문제
- 어떻게 풀어야 간단할까??
- 초록색 보드와 파란색 보드에 대한 처리를 함수 하나로 구현하면 편하기 때문에 파란색 보드를 시계방향으로 90도회전시켜서 생각한다.
풀이
1. 블록 처리
- 1번 블록: 초록색 보드와 파란색 보드 모두 1번 블록으로 처리
- 2번 블록: 초록색 보드는 2번 블록으로 파란색 보드는 3번 블록으로 처리
- 3번 블록: 초록색 보드는 3번 블록으로 파란색 보드는 2번 블록으로 처리
n = int(input())
green = [[0] * 4 for _ in range(6)]
blue = [[0] * 4 for _ in range(6)]
for _ in range(n):
t, x, y = map(int, input().split())
# t = 1 -> (x, y)
# t = 2 -> (x, y), (x, y + 1)
# t = 3 -> (x, y), (x + 1, y)
if t == 1:
monomino(green, y, 1)
monomino(blue, x, 1)
elif t == 2:
monomino(green, y, 2)
monomino(blue, x, 3)
else:
monomino(green, y, 3)
monomino(blue, x, 2)
2. 블록 내리기
- 해당 블록이 최대한 내려갈 수 있는 max_row를 계산한다.
- 2번 블록의 경우(가로로 두칸) 차지하는 두 인덱스의 max_row 중 최솟값을 이용한다.
def monomino(board, col, type):
max_row = -1
for i in range(6):
if board[i][col] == 0:
max_row = i
else:
break
if type == 2:
max_row2 = -1
for i in range(6):
if board[i][col + 1] == 0:
max_row2 = i
else:
break
max_row = min(max_row, max_row2)
board[max_row][col] = type
if type == 2:
board[max_row][col + 1] = type
elif type == 3:
board[max_row - 1][col] = type
while True:
if not delete(board):
break
3. 블록 삭제와 블록 내리기
- 블록을 삭제하고 빈칸으로 블록이 내려온 경우, 다시 블록을 삭제할 수 있는 상황이 생길 수 있으므로, while문으로 처리
- 블록이 더 이상 삭제되지 않는 경우 break
def delete(board):
global score
res = False
max_row = -1
for i in range(6):
flg = True
for j in range(4):
if board[i][j] == 0:
flg = False
# 블록 삭제
if flg:
score += 1
res = True
max_row = max(max_row, i)
for j in range(4):
board[i][j] = 0
# 블록 아래로 이동
for i in range(max_row, -1, -1):
for j in range(4):
if board[i][j] == 1 or board[i][j] == 3:
now = i + 1
while now < 6 and board[now][j] == 0:
board[now][j], board[now - 1][j] = board[now - 1][j], 0
now += 1
elif j < 3 and board[i][j] == 2 and board[i][j + 1] == 2:
now = i + 1
while now < 6 and board[now][j] == 0 and board[now][j + 1] == 0:
board[now][j], board[now][j + 1] = board[now - 1][j], board[now - 1][j + 1]
board[now - 1][j], board[now - 1][j + 1] = 0, 0
now += 1
return res
4. 특별한 칸 처리
- 보드의 연한 칸에 블록이 있는 경우 몇 칸을 차지하는지 계산하고 해당 cnt만큼 아래에서 블록을 삭제한다.
- 이후 블록을 다시 이동시키고 삭제할 블록을 처리하기 위해 delete 함수를 호출한다.
# 특별한 칸 처리
cnt = 0
for i in range(2):
flg = False
for j in range(4):
if board[i][j] != 0:
flg = True
if flg:
cnt += 1
if cnt > 0:
for i in range(5, -1, -1):
for j in range(4):
board[i][j] = 0
if i - cnt >= 0:
board[i][j] = board[i - cnt][j]
while True:
if not delete(board):
break
전체코드
def delete(board):
global score
res = False
max_row = -1
for i in range(6):
flg = True
for j in range(4):
if board[i][j] == 0:
flg = False
# 블록 삭제
if flg:
score += 1
res = True
max_row = max(max_row, i)
for j in range(4):
board[i][j] = 0
# 블록 아래로 이동
for i in range(max_row, -1, -1):
for j in range(4):
if board[i][j] == 1 or board[i][j] == 3:
now = i + 1
while now < 6 and board[now][j] == 0:
board[now][j], board[now - 1][j] = board[now - 1][j], 0
now += 1
elif j < 3 and board[i][j] == 2 and board[i][j + 1] == 2:
now = i + 1
while now < 6 and board[now][j] == 0 and board[now][j + 1] == 0:
board[now][j], board[now][j + 1] = board[now - 1][j], board[now - 1][j + 1]
board[now - 1][j], board[now - 1][j + 1] = 0, 0
now += 1
return res
def monomino(board, col, type):
max_row = -1
for i in range(6):
if board[i][col] == 0:
max_row = i
else:
break
if type == 2:
max_row2 = -1
for i in range(6):
if board[i][col + 1] == 0:
max_row2 = i
else:
break
max_row = min(max_row, max_row2)
board[max_row][col] = type
if type == 2:
board[max_row][col + 1] = type
elif type == 3:
board[max_row - 1][col] = type
while True:
if not delete(board):
break
# 특별한 칸 처리
cnt = 0
for i in range(2):
flg = False
for j in range(4):
if board[i][j] != 0:
flg = True
if flg:
cnt += 1
if cnt > 0:
for i in range(5, -1, -1):
for j in range(4):
board[i][j] = 0
if i - cnt >= 0:
board[i][j] = board[i - cnt][j]
while True:
if not delete(board):
break
if __name__ == '__main__':
n = int(input())
green = [[0] * 4 for _ in range(6)]
blue = [[0] * 4 for _ in range(6)]
score = 0
for _ in range(n):
t, x, y = map(int, input().split())
# t = 1 -> (x, y)
# t = 2 -> (x, y), (x, y + 1)
# t = 3 -> (x, y), (x + 1, y)
if t == 1:
monomino(green, y, 1)
monomino(blue, x, 1)
elif t == 2:
monomino(green, y, 2)
monomino(blue, x, 3)
else:
monomino(green, y, 3)
monomino(blue, x, 2)
print(score)
ans = 0
for i in range(6):
for j in range(4):
if green[i][j] != 0:
ans += 1
if blue[i][j] != 0:
ans += 1
print(ans)
'Python > Coding Test' 카테고리의 다른 글
13334 철로 (0) | 2022.02.15 |
---|---|
2485 가로수 (0) | 2022.02.14 |
16960 스위치와 램프 (0) | 2022.02.13 |
1781 컵라면 (0) | 2022.02.10 |
17175 피보나치는 지겨웡~ (0) | 2022.02.10 |