[백준] 21609번. 상어 중학교 🦈 바로가기
1. 아이디어
기능 구현
- 블록그룹 만들어서 가장 큰 블록그룹 제거하기
- 중력 작용 시키기
def down():
for y in range(n):
cnt = 0
for x in range(n-1, -1, -1):
if board[x][y] == -2:
cnt += 1
elif board[x][y] == -1:
cnt = 0
else:
if cnt != 0:
board[x + cnt][y] = board[x][y]
board[x][y] = -2
- 반시계방향으로 90도 회전 시키기 💡 암기하자
- 90도 반시계방향 회전 :
temp[n - 1 - y][x] = board[x][y]
def rotate():
temp = [[0] * n for _ in range(n)]
for x in range(n):
for y in range(n):
temp[n - 1 - y][x] = board[x][y]
for x in range(n):
for y in range(n):
board[x][y] = temp[x][y]
- 90도 시계방향 회전 :
temp[y][n - x - 1] = board[x][y]
from copy import deepcopy
def rotate(board):
temp = [[0] * n for _ in range(n)]
for x in range(n):
for y in range(n):
temp[y][n - x - 1] = board[x][y]
for x in range(n):
for y in range(n):
board[x][y] = temp[x][y]
코드
from collections import deque
def search_block_group():
point = 0
max_area_list = []
max_rainbow = 0
for color in range(1, m + 1):
visited = [[0] * n for _ in range(n)]
for x in range(n):
for y in range(n):
if board[x][y] == color and not visited[x][y]:
q = deque([(x, y)])
area_list = [(x, y)]
visited[x][y] = 1
rainbow = 0
while q:
cx, cy = q.popleft()
for d in range(4):
nx = cx + dx[d]
ny = cy + dy[d]
if 0 <= nx < n and 0 <= ny < n and not visited[nx][ny] and \
(board[nx][ny] == color or board[nx][ny] == 0):
q.append((nx, ny))
area_list.append((nx, ny))
visited[nx][ny] = 1
if board[nx][ny] == 0:
rainbow += 1
if (len(max_area_list) < len(area_list)) or\
(len(max_area_list) == len(area_list) and max_rainbow < rainbow) or\
(len(max_area_list) == len(area_list) and max_rainbow == rainbow and max_area_list[0][0] < area_list[0][0]) or\
(len(max_area_list) == len(area_list) and max_rainbow == rainbow and max_area_list[0][0] == area_list[0][0] and max_area_list[0][1] < area_list[0][1]):
max_area_list = area_list
max_rainbow = rainbow
if len(max_area_list) >= 2:
point += len(max_area_list) * len(max_area_list)
for block in max_area_list:
board[block[0]][block[1]] = -2
return point
def down():
for y in range(n):
cnt = 0
for x in range(n-1, -1, -1):
if board[x][y] == -2:
cnt += 1
elif board[x][y] == -1:
cnt = 0
else:
if cnt != 0:
board[x + cnt][y] = board[x][y]
board[x][y] = -2
def rotate():
temp = [[0] * n for _ in range(n)]
for x in range(n):
for y in range(n):
temp[n - 1 - y][x] = board[x][y]
for x in range(n):
for y in range(n):
board[x][y] = temp[x][y]
n, m = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(n)]
dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
total_point = 0
'''
오토 플레이
1. 크기가 가장 큰 블록 그룹을 찾는다.
(그러한 블록 그룹이 여러 개라면 포함된 무지개 블록의 수가 가장 많은 블록 그룹,
그러한 블록도 여러개라면 기준 블록의 행이 가장 큰 것을,
그 것도 여러개이면 열이 가장 큰 것을 찾는다.)
2. 1에서 찾은 블록 그룹의 모든 블록을 제거한다. 블록 그룹에 포함된 블록의 수를 B라고 했을 때, B2점을 획득한다.
3. 격자에 중력이 작용한다.
4. 격자가 90도 반시계 방향으로 회전한다.
5. 다시 격자에 중력이 작용한다.
'''
while True:
cur_point = search_block_group()
if cur_point == 0:
break
total_point += cur_point
down()
rotate()
down()
print(total_point)