Skip to content

Commit ce3ee41

Browse files
authored
Merge pull request #58 from YoonYn9915/main
YoonYn9915 / 8월 5주차 / 2문제
2 parents d7f8418 + 3dedf33 commit ce3ee41

4 files changed

+273
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from collections import deque
2+
import sys
3+
import copy
4+
5+
# 1. 입력값 받기
6+
# 2. 임의로 벽 3개 세우기 (backtracking 사용)
7+
# 3. bfs로 그래프 탐색하며 바이러스가 있는곳(처음에 2인 영역)부터 시작해서 바이러스 확산시키기
8+
# 4. 바이러스 확산 후 안전영역(0인 영역)을 세고 최대값이면 저장
9+
10+
11+
def bfs():
12+
global arr, virusLocation,N,M, maxSafeAreaCount
13+
14+
copyArr = copy.deepcopy(arr)
15+
16+
dx = [0,0,1,-1]
17+
dy = [1,-1,0,0]
18+
19+
queue = deque(virusLocation)
20+
21+
while queue:
22+
startRow,startCol = queue.popleft()
23+
for i in range(4):
24+
row = startRow + dx[i]
25+
col = startCol + dy[i]
26+
27+
if 0<=row<N and 0<=col<M and copyArr[row][col] == 0:
28+
#바이러스 확산
29+
copyArr[row][col] = 2
30+
#방문처리
31+
queue.append((row,col))
32+
33+
#안전영역 세기
34+
safeAreaCount = 0
35+
for i in range(N):
36+
for j in range(M):
37+
if copyArr[i][j] == 0:
38+
safeAreaCount += 1
39+
40+
#안전영역의 최댓값 비교
41+
maxSafeAreaCount = max(maxSafeAreaCount, safeAreaCount)
42+
43+
44+
def makeWall(arr, numOfWall):
45+
46+
# 세운 벽의 개수가 3개면 바이러스 확산시키기
47+
if numOfWall == 3:
48+
bfs()
49+
return
50+
51+
# 벽의 개수가 3이 아니면 하나씩 세우기
52+
for i in range(N):
53+
for j in range(M):
54+
if arr[i][j] == 0:
55+
arr[i][j] = 1
56+
makeWall(arr, numOfWall + 1)
57+
# 3개가 돼서 bfs가 끝나면 원복해주기
58+
arr[i][j] = 0
59+
60+
61+
#입력값 받기
62+
inp = sys.stdin.readline
63+
64+
N,M = map(int, inp().split())
65+
66+
arr = []
67+
for _ in range(N):
68+
arr.append(list(map(int, inp().split())))
69+
70+
#바이러스 위치 찾기
71+
virusLocation = []
72+
for i in range(N):
73+
for j in range(M):
74+
if arr[i][j] == 2:
75+
virusLocation.append((i,j))
76+
77+
maxSafeAreaCount = 0
78+
79+
makeWall(arr, 0)
80+
print(maxSafeAreaCount)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from collections import deque
2+
3+
dx = [1, 0, -1, 0]
4+
dy = [0, 1, 0, -1]
5+
6+
MAX = float('inf')
7+
8+
9+
def solution(board):
10+
N = len(board)
11+
answer = 0
12+
visited = set()
13+
q = deque([(0, 0, 0, 0)])
14+
15+
while q:
16+
x, y, r, t = q.popleft()
17+
if (x, y) == (N - 1, N - 1) or (x + dx[r], y + dy[r]) == (N - 1, N - 1):
18+
answer = t
19+
break
20+
if (x, y, r) in visited or (x + dx[r], y + dy[r], (r + 2) % 4) in visited:
21+
continue
22+
visited.add((x, y, r))
23+
24+
for i in range(4):
25+
ax, ay = x + dx[i], y + dy[i]
26+
if not -1 < ax < N or not -1 < ay < N or board[ay][ax] == 1:
27+
continue
28+
_ax, _ay = ax + dx[r], ay + dy[r]
29+
if not -1 < _ax < N or not -1 < _ay < N or board[_ay][_ax] == 1:
30+
continue
31+
q.append((ax, ay, r, t + 1))
32+
33+
for i in [-1, 1]:
34+
_r = (r + i) % 4
35+
ax, ay = x + dx[_r], y + dy[_r]
36+
if not -1 < ax < N or not -1 < ay < N or board[ay][ax] == 1:
37+
continue
38+
cx, cy = ax + dx[r], ay + dy[r]
39+
if board[cy][cx] == 1:
40+
continue
41+
q.append((x, y, _r, t + 1))
42+
43+
x, y, r = x + dx[r], y + dy[r], (r + 2) % 4
44+
for i in [-1, 1]:
45+
_r = (r + i) % 4
46+
ax, ay = x + dx[_r], y + dy[_r]
47+
if not -1 < ax < N or not -1 < ay < N or board[ay][ax] == 1:
48+
continue
49+
cx, cy = ax + dx[r], ay + dy[r]
50+
if board[cy][cx] == 1:
51+
continue
52+
q.append((x, y, _r, t + 1))
53+
54+
return answer
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from collections import deque
2+
3+
n, k = map(int, input().split())
4+
a = deque(map(int, input().split())) # 내구도. A1, A2, ..., A2N
5+
robot = deque([0] * n) # 벨트위에 있는 로봇
6+
result = 0
7+
8+
while True:
9+
result += 1
10+
# 1. 벨트 회전한다.
11+
a.rotate(1)
12+
robot[-1] = 0
13+
robot.rotate(1)
14+
robot[-1] = 0 # 내리는 위치에 도달한 경우, 즉시 내림
15+
# 2. 로봇 이동하기. 이동하려는 칸에 로봇 x, 내구도 1이상 남아야함.
16+
for i in range(n - 2, -1, -1): # 먼저 올라간 로봇부터 진행
17+
if a[i + 1] >= 1 and robot[i + 1] == 0 and robot[i] == 1:
18+
robot[i + 1] = 1
19+
robot[i] = 0
20+
a[i + 1] -= 1
21+
robot[-1] = 0 # 내리는 위치에 도달한 경우, 즉시 내림
22+
# 3. 올리는 위치에 내구도 0 아니면 로봇 올리기 & 내구도 감소
23+
if a[0] != 0 and robot[0] != 1:
24+
robot[0] = 1
25+
a[0] -= 1
26+
# 4. 내구도 0인 칸 수가 k이상이면 종료
27+
if a.count(0) >= k:
28+
break
29+
print(result)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
'''
2+
비바라기를 시전하면 (N, 1), (N, 2), (N-1, 1), (N-1, 2)에 비구름이 생긴다. 구름은 칸 전체를 차지한다. 이제 구름에 이동을 M번 명령하려고 한다. i번째 이동 명령은 방향 di과 거리 si로 이루어져 있다. 방향은 총 8개의 방향이 있으며, 8개의 정수로 표현한다. 1부터 순서대로 ←, ↖, ↑, ↗, →, ↘, ↓, ↙ 이다. 이동을 명령하면 다음이 순서대로 진행된다.
3+
4+
모든 구름이 di 방향으로 si칸 이동한다.
5+
각 구름에서 비가 내려 구름이 있는 칸의 바구니에 저장된 물의 양이 1 증가한다.
6+
구름이 모두 사라진다.
7+
2에서 물이 증가한 칸 (r, c)에 물복사버그 마법을 시전한다. 물복사버그 마법을 사용하면, 대각선 방향으로 거리가 1인 칸에 물이 있는 바구니의 수만큼 (r, c)에 있는 바구니의 물이 양이 증가한다.
8+
이때는 이동과 다르게 경계를 넘어가는 칸은 대각선 방향으로 거리가 1인 칸이 아니다.
9+
예를 들어, (N, 2)에서 인접한 대각선 칸은 (N-1, 1), (N-1, 3)이고, (N, N)에서 인접한 대각선 칸은 (N-1, N-1)뿐이다.
10+
바구니에 저장된 물의 양이 2 이상인 모든 칸에 구름이 생기고, 물의 양이 2 줄어든다. 이때 구름이 생기는 칸은 3에서 구름이 사라진 칸이 아니어야 한다.
11+
'''
12+
13+
from collections import deque
14+
15+
def copyWater(arr, cloudLoc):
16+
global N
17+
18+
# 대각선 방향의 dx와 dy설정
19+
dx = [-1, -1, 1, 1]
20+
dy = [-1, 1, -1, 1]
21+
22+
for loc in cloudLoc:
23+
increment = 0
24+
locX, locY = loc
25+
26+
for i in range(4):
27+
row = locX + dx[i]
28+
col = locY + dy[i]
29+
30+
if 0 <= row < N and 0 <= col < N and arr[row][col] > 0:
31+
increment += 1
32+
33+
arr[locX][locY] += increment
34+
35+
36+
def moveCloudDropRain(arr, d, s, index, cloudLoc):
37+
# 8가지 이동 경우의 수 설정 (d는 1부터 시작하므로 0-index로 맞춤)
38+
dx = [0, -1, -1, -1, 0, 1, 1, 1]
39+
dy = [-1, -1, 0, 1, 1, 1, 0, -1]
40+
41+
newCloudLoc = deque()
42+
43+
# 각 구름마다 이동
44+
for loc in cloudLoc:
45+
locX, locY = loc
46+
47+
locX = (locX + dx[d[index] - 1] * s[index]) % N
48+
locY = (locY + dy[d[index] - 1] * s[index]) % N
49+
50+
# 새로운 구름 위치 저장
51+
newCloudLoc.append((locX, locY))
52+
53+
# 이동한 구름 위치에 비 내림
54+
arr[locX][locY] += 1
55+
56+
cloudLoc.clear()
57+
cloudLoc.extend(newCloudLoc)
58+
59+
60+
# 비 바라기 수행. 비구름을 생성하고 M번만큼 구름을 이동시켜 비를 내린다.
61+
def makeRain(arr, d, s):
62+
global N, M
63+
64+
# 구름 위치 초기화
65+
initialCloudLocation = [(N - 1, 0), (N - 1, 1), (N - 2, 0), (N - 2, 1)]
66+
cloudLoc = deque(initialCloudLocation)
67+
68+
# 구름이 사라진 위치 저장
69+
disappearedCloudLoc = set()
70+
71+
for i in range(M):
72+
# 구름 이동 & 비내리기 함수
73+
moveCloudDropRain(arr, d, s, i, cloudLoc)
74+
75+
# 물 복사 함수
76+
copyWater(arr, cloudLoc)
77+
78+
# 구름이 사라진 위치 기록
79+
disappearedCloudLoc = set(cloudLoc)
80+
81+
# 새로운 구름 위치를 결정
82+
newCloudLoc = deque()
83+
for r in range(N):
84+
for c in range(N):
85+
# 2 이상의 물이 있고, 사라진 구름 위치가 아닌 경우에만 구름 생성
86+
if arr[r][c] >= 2 and (r, c) not in disappearedCloudLoc:
87+
newCloudLoc.append((r, c))
88+
arr[r][c] -= 2 # 물의 양 2 감소
89+
90+
cloudLoc = newCloudLoc
91+
92+
93+
N, M = map(int, input().split())
94+
arr = []
95+
d, s = [], []
96+
97+
# 초기 물의 양 저장
98+
for _ in range(N):
99+
arr.append(list(map(int, input().split())))
100+
101+
# M개의 이동 명령 저장
102+
for _ in range(M):
103+
temp = input().split()
104+
d.append(int(temp[0]))
105+
s.append(int(temp[1]))
106+
107+
# 비 바라기 수행
108+
makeRain(arr, d, s)
109+
total_sum = sum(sum(row) for row in arr)
110+
print(total_sum)

0 commit comments

Comments
 (0)