[BaekJoon] 백준 21609번 상어중학교
🎈문제
https://www.acmicpc.net/problem/21609
💬설명
- bfs, 구현 문제
- 따져줘야하는 조건이 많아서 까다로웠다.
- python으로 채점하면 시간초과가 나서 pypy로 채점해줬다.
- 좀더 깔끔하게 풀 수 있을 것 같은데 문제 잊었을 때 쯤 다시 풀어봐야겠다.
👩💻코드
# BaekJoon21609.py
from collections import deque
import copy
N, M = map(int, input().split())
result = 0
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
arr = [[] for _ in range(N)]
for i in range(N):
arr[i] = list(map(int, input().split()))
def gravity():
global arr, N
for i in range(N - 1, -1, -1):
for j in range(N - 1, -1, -1):
if arr[i][j] == -1 or arr[i][j] == -2:
continue
for k in range(i + 1, N):
# 아래에 다른 블럭이 있을 경우
if arr[k][j] != -2:
if i + 1 == k:
break
arr[k - 1][j] = arr[i][j]
arr[i][j] = -2
break
# 마지막 칸인 경우
if k >= N - 1:
arr[k][j] = arr[i][j]
arr[i][j] = -2
break
def solution():
global N, arr, dx, dy, result
while True:
selected_group = []
block_group = [] # 블록 그룹의 블록들 위치 좌표값 저장
visited = [[False] * N for _ in range(N)] # 방문 여부 저장
for i in range(N):
for j in range(N):
# 무지개 블록의 방문 여부 초기화
for k in range(N):
for t in range(N):
if arr[k][t] == 0:
visited[k][t] = False
# 일반블록이 아니거나 방문한 곳이면 continue
if arr[i][j] <= 0 or visited[i][j]:
continue
queue = deque([[i, j]])
visited[i][j] = True
block_group.append([[i, j]])
color = arr[i][j]
# bfs
while queue:
value = queue.popleft()
for k in range(4):
nx = value[0] + dx[k]
ny = value[1] + dy[k]
# 게임판 밖으로 넘어가면 continue
if nx >= N or ny >= N or nx < 0 or ny < 0:
continue
# 검은색 블록이거나 방문한 블록인 경우 continue
if arr[nx][ny] == -1 or arr[nx][ny] == -2 or visited[nx][ny]:
continue
# 다른색 일반블록인 경우 continue:
if arr[nx][ny] > 0 and arr[nx][ny] != color:
continue
block_group[-1].append([nx, ny])
queue.append([nx, ny])
visited[nx][ny] = True
# 가장 큰 블록 그룹 구하기
block_max = []
for group in block_group:
length = len(group)
# 블록 그룹 크기가 2 미만이면 블록 그룹 성립X
if length < 2:
continue
# 크기 비교 후, 큰 그룹 선택
if len(block_max) == 0:
block_max.append(copy.deepcopy(group))
continue
if len(block_max[0]) < length:
block_max = [copy.deepcopy(group)]
elif len(block_max[0]) == length:
block_max.append(copy.deepcopy(group))
# 블록 그룹이 존재하지 않는 경우
if len(block_max) == 0:
print(result)
break
# 크기가 큰 블록이 하나면 해당 그룹 선택
if len(block_max) == 1:
selected_group = copy.deepcopy(block_max[0])
else:
# 크기가 큰 블록이 둘 이상이면 무지개 블록 수로 그룹 선택
rainbow_blocks = []
for group in block_max:
rainbow_block = 0
for block in group:
if arr[block[0]][block[1]] == 0:
rainbow_block += 1
rainbow_blocks.append(rainbow_block)
rainbow_max = rainbow_blocks.count(max(rainbow_blocks))
# 무지개 블록 개수가 최대인 그룹이 하나면 해당 그룹 선택
if rainbow_max == 1:
selected_group = copy.deepcopy(block_max[rainbow_blocks.index(max(rainbow_blocks))])
else:
# 최대인 그룹이 둘 이상이면 기준 블록 구해서 행 크기로 선택
block_max = [block_max[i] for i in range(len(rainbow_blocks)) if rainbow_blocks[i] == max(rainbow_blocks)]
rep_blocks = []
for group in block_max:
group.sort(key=lambda x: (x[0], x[1]))
for block in group:
# 무지개 블록이 아닌 기준 블록
if arr[block[0]][block[1]] != 0:
rep_blocks.append(copy.deepcopy(block))
break
rep_blocks.sort(key=lambda x: (x[0], x[1]))
for group in block_max:
if rep_blocks[-1] in group:
selected_group = copy.deepcopy(group)
# selected_group 제거
for block in selected_group:
arr[block[0]][block[1]] = -2
# 점수 획득
result += len(selected_group) ** 2
# 중력 작용
gravity()
# 90도 반시계 회전
new_arr = copy.deepcopy(arr)
for i in range(N):
for j in range(N):
arr[i][j] = new_arr[j][N - i - 1]
# 중력 작용
gravity()
solution()
728x90
반응형
'CS > Algorithm 문제' 카테고리의 다른 글
[BaekJoon] 백준 4358번 생태학 (0) | 2021.10.12 |
---|---|
[BaekJoon] 백준 2170 선 긋기 (0) | 2021.10.11 |
[Programmers] 더 맵게 (0) | 2021.10.07 |
[Programmers] 주식가격 (0) | 2021.10.07 |
[Programmers] 다리를 지나는 트럭 (0) | 2021.10.07 |