https://www.acmicpc.net/problem/20061
처음에 문제 이해가 안돼서 한참 다시 읽었다.
✅ 문제 조건
1. 빨간색 보드에 블록을 놓으면, 초록색 보드와 파란색 보드로 블록 이동
1-1. 초록색 보드
- 열 고정된 상태로 아래방향으로 블록 떨어짐
- 가로 줄이 모두 차면 제거, 위에 있는 블록은 아래로 이동
- 0, 1번 행 중 블록이 있으면, 가장 아래 행부터 차례로 한 줄씩 삭제, 비원진 만큼 위에서 밀어내림
1-2. 파란색 보드
- 행 고정된 상태로 오른쪽방향으로 블록 떨어짐
- 세로 줄이 모두 차면 제거, 왼쪽에 있는 블록은 오른쪽으로 이동
- 0, 1번 열 중 블록이 있으면, 가장 오른쪽 열부터 차례로 한 줄씩 삭제, 비워진 만큼 왼쪽에서 밀어내림
2. 주어진 사이클만큼 블록 이동후, 획득한 점수와 최종 보드 위의 블록 수 출력
✅ 접근 방식
일단 세가지 함수로 분리했다.
1. 매 사이클마다 블록 떨어뜨리는 함수
2. 블록이 각 행 또는 열마다 꽉 찼으면 해당 라인 삭제 후 점수 획득하는 함수
3. 연한칸의 (0, 1 열 또는 0, 1 행) 블록 유무 체크 후 라인 삭제하는 함수
💡 보드 배열 갱신
처음에는 보드의 라인을 정리하는 방법으로
new_arr = [line[:] for line in arr]
이런 깊은복사를 사용해서 새로운 배열을 생성하고 거기에 정리된 블록을 추가하려고 했다.
근데 구현하다보니 배열의 크기도 작고 참조가 끊어지지 않게 하고싶어서 pop, insert 방식으로 바꿨다.
✅ 구현
0. 입력 및 배열 초기화
N = int(input())
blue = [[0] * 6 for _ in range(4)]
green = [[0] * 4 for _ in range(6)]
score = 0
for _ in range(N):
t, x, y = map(int, input().split())
1. 매 사이클마다 블록 떨어뜨리는 함수
def drop_block(t, x, y):
# 초록 보드
if t == 1:
r = 0
while r+1 < 6 and green[r+1][y] == 0:
r += 1
green[r][y] = 1
elif t == 2:
r = 0
while r+1 < 6 and green[r+1][y] == 0 and green[r+1][y+1] == 0:
r += 1
green[r][y] = 1
green[r][y+1] = 1
elif t == 3:
r = 0
while r+2 < 6 and green[r+2][y] == 0:
r += 1
green[r][y] = 1
green[r+1][y] = 1
# 파란 보드
if t == 1:
c = 0
while c+1 < 6 and blue[x][c+1] == 0:
c += 1
blue[x][c] = 1
elif t == 2:
c = 0
while c+2 < 6 and blue[x][c+2] == 0:
c += 1
blue[x][c] = 1
blue[x][c+1] = 1
elif t == 3:
c = 0
while c+1 < 6 and blue[x][c+1] == 0 and blue[x+1][c+1] == 0:
c += 1
blue[x][c] = 1
blue[x+1][c] = 1
입력받은 t, x, y (블록 타입, 빨간 보드에 블록을 놓는 위치 x, y)를 파타미터로 바로 받아서
타입별로 블록을 밀면서 위치를 고정했다.
2. 블록이 각 행 또는 열마다 꽉 찼으면 해당 라인 삭제 후 점수 획득하는 함수
def check_line():
global score
# 초록
while True:
found = False
for i in range(5, 1, -1):
if all(green[i]):
score += 1
found = True
for r in range(i, 0, -1):
green[r] = green[r - 1][:]
green[0] = [0] * 4
break
if not found:
break
# 파랑
while True:
found = False
for j in range(5, 1, -1):
if all(blue[r][j] for r in range(4)):
score += 1
found = True
for c in range(j, 0, -1):
for r in range(4):
blue[r][c] = blue[r][c - 1]
for r in range(4):
blue[r][0] = 0
break
if not found:
break
그리고 블록을 옮긴 후 꽉 찬 라인이 있는지 확인했다.
꽉 찬 라인이 있으면 다음 라인을 옮기면서 갱신했다.
초기 구현 결과, 이 과정에서 라인을 한번만 확인하고 다음을 계속 확인하지 않아서 틀렸다.
3. 연한칸의 (0, 1 열 또는 0, 1 행) 블록 유무 체크 후 라인 삭제하는 함수
def check_light():
# 초록
cnt = 0
for i in [0, 1]:
if any(green[i]):
cnt += 1
for _ in range(cnt):
green.pop()
green.insert(0, [0]*4)
# 파랑
cnt = 0
for j in [0, 1]:
if any(blue[i][j] for i in range(4)):
cnt += 1
for _ in range(cnt):
for r in range(4):
blue[r].pop()
blue[r].insert(0, 0)
그리고 연한칸에 블록이 있을 경우 한번 더 맨 끝 라인을 삭제 후 블록을 밀어줬다.
✅ 정답 코드
'''
- 블록 타입 : 1*1, 1*2, 2*1
- 초록 보드
- 열 고정된 상태로 아래방향으로 블록 떨어짐
- 가로 줄이 모두 차면 제거, 위에 있는 블록은 아래로 이동
- 0, 1번 행 중 블록이 있으면, 가장 아래 행부터 차례로 한 줄씩 삭제, 비원진 만큼 위에서 밀어내림
- 파란 보드
- 행 고정된 상태로 오른쪽방향으로 블록 떨어짐
- 세로 줄이 모두 차면 제거, 왼쪽에 있는 블록은 오른쪽으로 이동
- 0, 1번 열 중 블록이 있으면, 가장 오른쪽 열부터 차례로 한 줄씩 삭제, 비워진 만큼 왼쪽에서 밀어내림
'''
N = int(input())
blue = [[0] * 6 for _ in range(4)]
green = [[0] * 4 for _ in range(6)]
score = 0
# 블록 떨어뜨리기
def drop_block(t, x, y):
# 초록 보드
if t == 1:
r = 0
while r+1 < 6 and green[r+1][y] == 0:
r += 1
green[r][y] = 1
elif t == 2:
r = 0
while r+1 < 6 and green[r+1][y] == 0 and green[r+1][y+1] == 0:
r += 1
green[r][y] = 1
green[r][y+1] = 1
elif t == 3:
r = 0
while r+2 < 6 and green[r+2][y] == 0:
r += 1
green[r][y] = 1
green[r+1][y] = 1
# 파란 보드
if t == 1:
c = 0
while c+1 < 6 and blue[x][c+1] == 0:
c += 1
blue[x][c] = 1
elif t == 2:
c = 0
while c+2 < 6 and blue[x][c+2] == 0:
c += 1
blue[x][c] = 1
blue[x][c+1] = 1
elif t == 3:
c = 0
while c+1 < 6 and blue[x][c+1] == 0 and blue[x+1][c+1] == 0:
c += 1
blue[x][c] = 1
blue[x+1][c] = 1
# 줄 제거 및 점수 계산
def check_line():
global score
# 초록
while True:
found = False
for i in range(5, 1, -1):
if all(green[i]):
score += 1
found = True
for r in range(i, 0, -1):
green[r] = green[r - 1][:]
green[0] = [0] * 4
break
if not found:
break
# 파랑
while True:
found = False
for j in range(5, 1, -1):
if all(blue[r][j] for r in range(4)):
score += 1
found = True
for c in range(j, 0, -1):
for r in range(4):
blue[r][c] = blue[r][c - 1]
for r in range(4):
blue[r][0] = 0
break
if not found:
break
# 연한 칸 확인
def check_light():
# 초록
cnt = 0
for i in [0, 1]:
if any(green[i]):
cnt += 1
for _ in range(cnt):
green.pop()
green.insert(0, [0]*4)
# 파랑
cnt = 0
for j in [0, 1]:
if any(blue[i][j] for i in range(4)):
cnt += 1
for _ in range(cnt):
for r in range(4):
blue[r].pop()
blue[r].insert(0, 0)
for _ in range(N):
t, x, y = map(int, input().split())
drop_block(t, x, y)
check_line()
check_light()
print(score)
print(sum(sum(line) for line in green) + sum(sum(line) for line in blue))
파이썬 아니었으면 못풀었을 거 같다..
'algorithm > Implementation' 카테고리의 다른 글
[백준17822/골드2] 원판 돌리기 - Python (0) | 2025.03.30 |
---|---|
[백준17143/골드1] 낚시왕 - Python (0) | 2025.03.25 |
[백준15685/골드3] 드래곤 커브 - Python (0) | 2025.03.17 |
[백준2422/실버4] 한윤정이 이탈리아에서 아이스크림을 사먹는데 - Python (0) | 2025.02.27 |
[백준17825/골드2] 주사위 윷놀이 - Python (3) | 2025.01.23 |