728x90
#17144 미세먼지 안녕! https://www.acmicpc.net/problem/17144
17144번: 미세먼지 안녕!
미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사
www.acmicpc.net
토요일에 시도했다가 포기하고 죽어있었다.
뭔가 잘못 구현한 부분이 있었는데 눈에 보이지 않았기 때문이다.
하지만 해결해냈다.
문제는 다음과 같았다.
먼지 데이터를 조금 더 효율적으로 관리하고 싶었다.
그래서 먼지의 위치를 저장한 리스트를 만들었었는데
공기청정기가 작동하게되면 먼지의 위치가 바뀐다.
이걸 반영을 안해줬기 때문에 문제가 발생했다.
이걸 파악한 뒤, 먼지의 확산 - 이동이 발생하기 전에 먼지의 위치를 별도로 파악했다.
하지만 이렇게 변경함으로 인해서 효율성은 훨씬 떨어졌다.
sys.stdin.readline, deque를 적용한 뒤, 채점 언어를 pypy3로 변경하고서야 겨우 통과했다.
구현은 너무나 힘든 것 같다 ㅜㅜ
import sys
from collections import deque
input = sys.stdin.readline
#### 입력 받을 변수 정의하기
# 지도 정보 저장
maps = []
# 공기청정기 정보 저장
cleaner = []
#### 입력받기
r, c, t = map(int, input().split())
# 지도 정보 입력받기
for y in range(r):
row = input().split()
for x in range(c):
tmp = int(row[x])
if tmp == -1: # is cleaner
cleaner.append([y, x])
row[x] = tmp
maps.append(row)
# for m in maps:
# print(m)
# print("cleaner : ", cleaner)
#### 필요한 함수 미리 저장하기
# 올바른 좌표인지 확인하기
def valid_pos(y, x):
if 0 <= y < r and 0 <= x < c: # 올바른 칸인가?
if maps[y][x] != -1: # 공기청정기가 아닌가?
return True
return False
# 먼지 저장 리스트
#### 실행하기 (여기부터 t 회 만큼 실행되어야한다.)
while t:
t -= 1
# 먼지 찾기
dusts = deque() # [y, x]
for y in range(r):
for x in range(c):
if maps[y][x] > 0:
dusts.append([y, x])
# 이동하는 먼지 정보 저장. -> 한번에 적용하기
move_dusts = deque() # [y, x, amount] 이렇게 저장하기
### 1. 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
# 움직이는 방향
## (r, c)에 있는 미세먼지는 인접한 네 방향으로 확산된다.
moves = [[-1, 0], [1, 0], [0, 1], [0, -1]]
while dusts:
y, x = dusts.popleft()
amount = maps[y][x]
## 확산되는 양은 Ar,c/5이고 소수점은 버린다. 즉, ⌊Ar,c/5⌋이다.
move_amount = amount // 5
if move_amount > 0:
cnt = 0
for my, mx in moves:
ny, nx = y + my, x + mx
## 인접한 방향에 공기청정기가 있거나, 칸이 없으면 그 방향으로는 확산이 일어나지 않는다.
if valid_pos(ny, nx):
# 이동 정보 저장
move_dusts.append([ny, nx, move_amount])
cnt += 1
## (r, c)에 남은 미세먼지의 양은 Ar,c - ⌊Ar,c/5⌋×(확산된 방향의 개수) 이다.
amount -= move_amount * cnt
maps[y][x] = amount
## 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
while move_dusts:
y, x, amount = move_dusts.popleft()
maps[y][x] += amount
# print("확산 후 : ")
# for m in maps:
# print(m)
### 2. 공기청정기가 작동한다. 공기청정기에서는 바람이 나온다.
## 위쪽 공기청정기의 바람은 반시계방향으로 순환하고
u_y, u_x = cleaner[0]
prev = 0 # 공기청정기에서 나오는 바람은 먼지가 없다.
# 오른쪽 이동
for x in range(u_x + 1, c):
now = maps[u_y][x]
maps[u_y][x] = prev
prev = now
# 맨 오른쪽 칸에서에서 위쪽 이동
for y in range(u_y - 1, -1, -1):
now = maps[y][c - 1]
maps[y][c - 1] = prev
prev = now
# 맨 오른쪽 맨 위에서 왼쪽 이동
for x in range(c - 2, -1, -1):
now = maps[0][x]
maps[0][x] = prev
prev = now
# 맨 왼쪽 위에서 아래쪽 이동
for y in range(1, u_y):
now = maps[y][u_x]
maps[y][u_x] = prev
prev = now
## 아래쪽 공기청정기의 바람은 시계방향으로 순환한다.
d_y, d_x = cleaner[1]
prev = 0 # 공기청정기에서 나오는 바람은 먼지가 없다.
# 오른쪽 이동
for x in range(d_x + 1, c): # 인덱스 맞는지 확인하기
now = maps[d_y][x]
maps[d_y][x] = prev
prev = now
# 맨 오른쪽 칸에서 아래 이동
for y in range(d_y + 1, r):
now = maps[y][c - 1]
maps[y][c - 1] = prev
prev = now
# 맨 오른쪽 아래에서 왼쪽 이동
for x in range(c - 2, -1, -1):
now = maps[r - 1][x]
maps[r - 1][x] = prev
prev = now
# 맨 왼쪽 아래에서 위쪽 이동
for y in range(r - 2, d_y, -1):
now = maps[y][d_x]
maps[y][d_x] = prev
prev = now
## 바람이 불면 미세먼지가 바람의 방향대로 모두 한 칸씩 이동한다.
## 공기청정기에서 부는 바람은 미세먼지가 없는 바람이고, 공기청정기로 들어간 미세먼지는 모두 정화된다.
# print("공기청정기 작동 후 :")
# for m in maps:
# print(m)
answer = 0
for y in range(r):
for x in range(c):
if maps[y][x] > 0:
answer += maps[y][x]
print(answer)
확실히 문제의 요구사항을 주석으로 꼼꼼히 달면서 풀이하는게 좋은 것 같다.
'Algorithm > acmicpc.net' 카테고리의 다른 글
파이썬 정렬이란2 (#11652 카드) (0) | 2024.06.24 |
---|---|
파이썬 정렬이란 (#10825 국영수) (0) | 2024.06.24 |
구현은 빡시다. (#15683 감시) (0) | 2024.03.27 |
카운팅은 애매하다. (#3190 뱀) (2) | 2024.03.27 |
좌표를 헷갈리지 말 것!! (#14499 주사위 굴리기) (2) | 2024.03.23 |