일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 공업수학
- 스피치 연습
- 공수
- 백준
- 미분방정식
- Python
- 미방
- vocabulary
- Homogeneous ODEs
- 비제차 상미분 방정식
- Nonhomogeneous ODEs
- 공학수학
- Conversation
- homogeneous
- 삼성SW역량테스트
- Advanced Engineering Mathematics
- 코딩테스트
- Ode
- SW역량테스트
- 공수 문제풀이
- Problem set 2.7
- Problem Set 1.4
- kreyszig
- English
- speech
- 공수1
- Problem set 1.5
- 문제풀이
- 영어회화
- ODEs
- Today
- Total
한걸음
백준 23290 : 마법사 상어와 복제 본문
https://www.acmicpc.net/problem/23290
23290번: 마법사 상어와 복제
첫째 줄에 물고기의 수 M, 상어가 마법을 연습한 횟수 S가 주어진다. 둘째 줄부터 M개의 줄에는 물고기의 정보 fx, fy, d가 주어진다. (fx, fy)는 물고기의 위치를 의미하고, d는 방향을 의미한다. 방향
www.acmicpc.net
1. 차근차근해봅시다.
반년만에 다시 풀어보는 문제. 구현할게 너무나도 많다. 본 문제에서는 크게 3가지로 쪼개서 생각했다.
- copy() : 초기에 물고기 위치들을 복사해준다.
- move() : 물고기 먼저 움직여주고, 그다음 상어가 이동할 곳을 찾아 이동한다.
- diminish() : 냄새를 하나씩 지워준다.
먼저 copy().
복사하는 것은 어렵지 않다. 굳이 함수로 안 만들어도 되긴 하는데 그냥 만들었다.
def copy():
return [arr for arr in f_info]
두 번째로 move().
물고기의 새로운 위치들을 담을 b_temp 배열을 만들었다. board에 있는 것들을 가져다가 할 수도 있지만 알아보기 쉽게 하기 위해서 임시 보드에다가 새 좌표를 넣어주고 그것을 board에 다시 업데이트하는 식으로 했다. 블로그 작성하면서 생각해보니 그냥 board만 활용해도 될 듯?
f_info에서 물고기 위치 정보들을 불러와서 길을 탐색한다. 8방향을 다 탐색해도 갈 곳이 없을 때에는 자기 자리에서 그대로 있도록 한다.
# fish
b_temp = [[[] for _ in range(4)] for _ in range(4)]
for i, (x, y, d) in enumerate(f_info) :
cnt = 0
while True :
nx = x + fdx[d]
ny = y + fdy[d]
if cnt == 8 : break
if nx < 0 or nx >= 4 or ny < 0 or ny >= 4 :
d = (d - 1) % 8
cnt += 1
continue
if 0 <= nx < 4 and 0 <= ny < 4 :
if smell[nx][ny] > 0 or [nx, ny] == [sx, sy] :
d = (d - 1) % 8
cnt += 1
continue
elif smell[nx][ny] == 0 :
b_temp[nx][ny].append(d)
break
if cnt == 8 :
b_temp[x][y].append(d)
# Board Update
for i in range(4):
for j in range(4):
board[i][j] = b_temp[i][j]
이제 상어를 움직여줘야 한다. 상어의 움직임에 관한 정보는 64가지 밖에 안되니, 완전 탐색으로 확인해주었다. 여기서 주의해야 할 것은 상어가 갔던 길을 다시 돌아갈 수도 있다는 점이다! [상, 하, 상] 같은 경우가 가능하니 이점 주의해주어야 한다. 이것 때문에 좀 헤맸다. 상어가 가는 길에 따른 물고기 먹을 수 있는 수는 딕셔너리로 관리했다. try & except을 이용해서 쉽게 만들 수 있고, 사전 순서에 맞게 경우의 수를 배치했으니 물고기를 먹을 수 있는 가장 큰 값의 0번째 인덱스를 사용하면 된다. 소스코드는 다음과 같다.
# shark : Count 3, Fish
temp = {}
for d1, d2, d3 in comb :
cnt = 0
check = True
x, y = sx, sy
visited = [[False for _ in range(4)] for _ in range(4)]
for d in [d1, d2, d3] :
nx = x + dx[d]
ny = y + dy[d]
if nx < 0 or nx >= 4 or ny < 0 or ny >= 4 :
check = False
break
elif 0 <= nx < 4 and 0 <= ny < 4 :
if not visited[nx][ny] :
if len(board[nx][ny]) >= 1 :
cnt += len(board[nx][ny])
visited[nx][ny] = True
x, y = nx, ny
else :
x, y = nx, ny
if check :
try :
temp[cnt] += [[d1, d2, d3]]
except :
temp[cnt] = [[d1, d2, d3]]
else :
continue
maxKey = max(temp)
x, y = sx, sy
for d in temp[maxKey][0] :
nx = x + dx[d]
ny = y + dy[d]
if len(board[nx][ny]) >= 1 :
board[nx][ny] = []
smell[nx][ny] = 3
x, y = nx, ny
sx, sy = nx, ny
size = len(f_info)
del f_info[:size]
for i in range(4):
for j in range(4):
if len(board[i][j]) >= 1 :
for k in range(len(board[i][j])):
f_info.append([i, j, board[i][j][k]])
마지막으로 diminish(),
이것 또한 쉽게 할 수 있다.
def diminish():
for i in range(4):
for j in range(4):
if smell[i][j] > 0 :
smell[i][j] -= 1
2. 전체 코드
메모리 : 361892 KB, 시간 : 952 ms, 풀이 시간 : 90분
M, S = map(int, input().split())
f_info = [list(map(int, input().split())) for _ in range(M)]
board = [[[] for _ in range(4)] for _ in range(4)]
smell = [[0 for _ in range(4)] for _ in range(4)]
sx, sy = map(int, input().split())
sx -= 1
sy -= 1
for i in range(len(f_info)):
f_info[i][0] -= 1
f_info[i][1] -= 1
f_info[i][2] -= 1
# 초기조건
for i in range(len(f_info)):
board[f_info[i][0]][f_info[i][1]].append(f_info[i][2]) # fish
comb = []
for i in range(4):
for j in range(4):
for k in range(4):
comb.append([i, j, k])
# 상, 좌, 하, 우 for shark
dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
# 좌, 좌상, 상, 상우, 우, 우하, 하, 하좌 for fish
fdx = [0, -1, -1, -1, 0, 1, 1, 1]
fdy = [-1, -1, 0, 1, 1, 1, 0, -1]
def copy():
return [arr for arr in f_info]
def move():
global sx, sy
# fish
b_temp = [[[] for _ in range(4)] for _ in range(4)]
for i, (x, y, d) in enumerate(f_info) :
cnt = 0
while True :
nx = x + fdx[d]
ny = y + fdy[d]
if cnt == 8 : break
if nx < 0 or nx >= 4 or ny < 0 or ny >= 4 :
d = (d - 1) % 8
cnt += 1
continue
if 0 <= nx < 4 and 0 <= ny < 4 :
if smell[nx][ny] > 0 or [nx, ny] == [sx, sy] :
d = (d - 1) % 8
cnt += 1
continue
elif smell[nx][ny] == 0 :
b_temp[nx][ny].append(d)
break
if cnt == 8 :
b_temp[x][y].append(d)
# Board Update
for i in range(4):
for j in range(4):
board[i][j] = b_temp[i][j]
# shark : Count 3, Fish
temp = {}
for d1, d2, d3 in comb :
cnt = 0
check = True
x, y = sx, sy
visited = [[False for _ in range(4)] for _ in range(4)]
for d in [d1, d2, d3] :
nx = x + dx[d]
ny = y + dy[d]
if nx < 0 or nx >= 4 or ny < 0 or ny >= 4 :
check = False
break
elif 0 <= nx < 4 and 0 <= ny < 4 :
if not visited[nx][ny] :
if len(board[nx][ny]) >= 1 :
cnt += len(board[nx][ny])
visited[nx][ny] = True
x, y = nx, ny
else :
x, y = nx, ny
if check :
try :
temp[cnt] += [[d1, d2, d3]]
except :
temp[cnt] = [[d1, d2, d3]]
else :
continue
maxKey = max(temp)
x, y = sx, sy
for d in temp[maxKey][0] :
nx = x + dx[d]
ny = y + dy[d]
if len(board[nx][ny]) >= 1 :
board[nx][ny] = []
smell[nx][ny] = 3
x, y = nx, ny
sx, sy = nx, ny
size = len(f_info)
del f_info[:size]
for i in range(4):
for j in range(4):
if len(board[i][j]) >= 1 :
for k in range(len(board[i][j])):
f_info.append([i, j, board[i][j][k]])
def diminish():
for i in range(4):
for j in range(4):
if smell[i][j] > 0 :
smell[i][j] -= 1
def solve():
it = 0
while it < S :
copy_fish = copy()
move()
diminish()
for x, y, d in copy_fish :
f_info.append([x, y, d])
board[x][y].append(d)
it += 1
result = 0
for i in range(4):
for j in range(4):
if len(board[i][j]) > 0 :
result += len(board[i][j])
print(result)
solve()
'Coding Test' 카테고리의 다른 글
백준 2536 : 버스 갈아타기 (4) | 2023.11.21 |
---|---|
백준 4963 : 섬의 개수 (2) | 2023.11.20 |
백준 2638 : 치즈 (0) | 2023.11.18 |
백준 3085 : 사탕 게임 (0) | 2023.11.16 |
백준 9205 : 맥주 마시면서 걸어가기 (1) | 2023.11.14 |