- 문제 : https://www.acmicpc.net/problem/16234

 

문제 이해 

- 특정 지점을 중심으로 bfs 탐색을 하면서 조건에 만족하는 노드를 모은 다음 전체의 평균으로 값을 업데이트하는 문제다.

- bfs 로직은 그렇게 어렵지 않았는데, 헷갈렸던 부분이 어떤 부분으로 bfs를 시작할지였다. while문에 이중 for문을 사용해야할 것 같은데 문제보니까 같은 지점도 중복으로 인구이동을 하는 것 같은데 이거를 어떻게 해야할지 몰랐다.

- 그래서 풀이를 보니까 while문을 시작할 때 visit를 초기화해서 방문하지 않은 지점을 중심으로 bfs를 하고, bfs 하면서 조건을 만족했던 지점들을 배열로 문제를 해결했다. 

- 반환한 배열(result)을 조건에 따라 인구이동을 하면 된다.

 

풀이 로직 

- n, l, r 과 matrix를 입력값으로 받는다. 

- while문을 돌면서 visit를 새로 설정하고 이중 for문을 돌면서 방문하지 않은 지점들을 중심으로 bfs를 진행한다. bfs를 통해 인구이동을 할 수 있는 노드들의 위치를 result로 가져온다. 이때 인구이동을 하므로 flag = True로 설정한다.

- result의 원소 개수가 2개 이상이라면 인구 이동을 할 수 있으므로 인구이동을 한다. 

인구 이동 로직은 다음과 같다. 각 지점의 matrix 값을 모두 더한 다음에 전체 개수를 나눠서 각 result 지점에 덮어씌워주면 된다. 

# 인구 이동을 할 수 있을 때
if len(result) >= 2:
	flag = True
	total = 0
	for i, j in result:
		total += matrix[i][j]
		temp = total // len(result)
	for i, j in result:
		matrix[i][j] = temp

- 더이상 인구 이동을 하지 않으면 이중 for문을 나왔을 때 flag == False 이므로 그때 while문을 나와주고, 아니라면 다시 처음부터 시작한다.

 

정답 풀이 

- bfs

def bfs(x, y, matrix, visit):
    visit[x][y] = 1
    result = [[x, y]]
    queue = [[x, y]]
    while queue:
        x, y = queue.pop(0)
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if 0 <= nx < n and 0 <= ny < n:
                if not visit[nx][ny] and l <= abs(matrix[nx][ny] - matrix[x][y]) <= r:
                    visit[nx][ny] = 1
                    queue.append([nx, ny])
                    result.append([nx, ny]) 
    return result

 

- 인구 이동

# 인구 이동을 할 수 있을 때
if len(result) >= 2:
	flag = True
	total = 0
	for i, j in result:
		total += matrix[i][j]
		temp = total // len(result)
	for i, j in result:
		matrix[i][j] = temp

 

- 전체 코드

def bfs(x, y, matrix, visit):
    visit[x][y] = 1
    result = [[x, y]]
    queue = [[x, y]]
    while queue:
        x, y = queue.pop(0)
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if 0 <= nx < n and 0 <= ny < n:
                if not visit[nx][ny] and l <= abs(matrix[nx][ny] - matrix[x][y]) <= r:
                    visit[nx][ny] = 1
                    queue.append([nx, ny])
                    result.append([nx, ny]) 
    return result
    
n, l, r = map(int, input().split())
matrix = []
dx, dy = [-1, 1, 0, 0], [0, 0, -1, 1]
for _ in range(n):
    matrix.append(list(map(int, input().split())))
    
answer = 0
while True:
    flag = False
    visit = [[0] * n for _ in range(n)]
    for x in range(n):
        for y in range(n):
            if not visit[x][y]:
                result = bfs(x, y, matrix, visit)
                # 인구 이동을 할 수 있을 때
                if len(result) >= 2:
                    flag = True
                    total = 0
                    for i, j in result:
                        total += matrix[i][j]
                    temp = total // len(result)
                    for i, j in result:
                        matrix[i][j] = temp
                                       
    if flag == False:
        break
        
    answer += 1
        
print(answer)

'백준 > Search' 카테고리의 다른 글

[bfs/백준] 5427번 : 불  (0) 2023.05.22
[bfs/백준] 2206번 : 벽 부수고 이동하기  (0) 2023.05.20
[bfs/백준] 7576번 : 토마토  (0) 2023.05.17
[bfs/백준] 6593번 : 상범 빌딩  (0) 2023.05.16
[bfs/백준] 5014번 : 스타트링크  (0) 2023.05.16

- 문제 : https://www.acmicpc.net/problem/7576

 

문제 이해 

- 2차 행렬이 주어지는데 1은 토마토가 있는 곳, -1은 박스가 있어서 이동을 못하고, 0은 토마토가 있는 부분이다. 

- 토마토가 있는 1을 중심으로 상하좌우에 0인 지점들로 bfs를 진행하는 문제다. 

- 풀면서 헷갈렸던 부분이 처음에 1인 지점(토마토가 있는 지점)이 여러개 있을텐데 이게 어떻게 동시다발적으로 진행시키지?였다. 

좀 헤매다가 답을 보니 처음에 행렬이 주어질 때 1인 지점들을 미리 queue에 담아두었다가 그거를 중심으로 bfs를 진행하면 된다. 

 

풀이 로직

- 입력값 n, m, matrix를 저장하고 matrix를 입력받을 때 1인 지점은 따로 queue에 저장한다.

- bfs를 실행하는데 방문여부는 visit로, 토마토 개수는 matrix를 이용해서 기록한다. 

- bfs를 끝낸 뒤 행렬을 전체 탐색하면서 0인 지점(안 익은 토마토)이 있으면 실패이고, 없다면 전체 값 중에 최대값을 출력하면 된다.

실패 여부는 flag를 이용해서 matrix에서 0인 지점이 있다면 False 처리한다. 

- flag 값에 따라 값을 다르게 출력해준다.

 

정답 풀이 

이전에 풀 때는 엄청 쉬웠던 것 같은데 다시 풀려니까 쉽지않다^^;

from collections import deque

def bfs():
    dx, dy = [-1, 1, 0, 0], [0, 0, -1, 1]
    while queue : 
        x, y = queue.popleft()
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if 0 <= nx < n and 0 <= ny < m:
                if not visit[nx][ny] and matrix[nx][ny] == 0:
                    visit[nx][ny] = 1
                    matrix[nx][ny] = matrix[x][y] + 1
                    queue.append([nx, ny])
                    
        
m, n = map(int, input().split())
matrix = []
queue = deque()
for i in range(n):
    matrix.append(list(map(int, input().split())))
    for j in range(m):
        if matrix[i][j] == 1:
            queue.append([i, j])


visit = [[0] * m for _ in range(n)]
bfs()
            
answer = 0
flag = True
for i in range(n):
    if 0 in matrix[i]:
        flag = False
        break
    else:
        answer = max(answer, max(matrix[i]))
        
if flag == True:    
    print(answer - 1)
else:
    print(-1)

- 문제 : https://www.acmicpc.net/problem/6593

 

Gold Lv5 문제이고, 답없이 풀었다. 

기본 bfs 문제에서 행렬이 3차원으로만 바뀐 건데 전체 행렬 입력받는데 인덱스를 잘못 설정해 IndexError가 많이 발생해서 시간이 좀 걸렸다. 

 

문제 이해 

- 여러 테스트케이스가 주어지고, 각 케이스마다 l, c, r 값이 주어지는데 2차원 행렬이 l개씩 입력된다. 

- 입력된 3차원 행렬들을 가지고 ' . '인 지점으로 탐색하면서 S에서 시작해 E로 가는 최소 경로 수를 출력한다. 

- 주의해야할 점이 총 3가지가 있다. 이거를 생각 안해서 IndexError로 헤맸다.

1. 인덱스 값을 주의해야 한다. matrix[a][b][c]는 a 층의 행렬의 b행 c열을 의미한다. 이를 x, y, z로 바꾸면 z, x, y가 된다. 

2. 위, 아래, 상, 하, 좌, 우 로 움직이므로 총 6개의 이동이있어서 dc, da, db를 다음과 같이 정의해야한다. 처음에dc = [-1, 1]로 설정했는데 이렇게 하면 대각선 위아래로 움직이므로 틀린 움직임 된다. 그래서 세 개의 배열 모두 길이 6이어야 한다.

dc, da, db = [-1, 1, 0, 0, 0, 0], [0, 0, -1, 1, 0, 0], [0, 0, 0, 0, -1, 1]

3. 마지막으로는 처음에 주어지는 값들이다. 빈칸 없이 연속으로 리스트가 주어지는 것이 아닌 i층이 끝나면 마지막에 아무것도 없는 빈줄이 입력되는데, 이를 고려해서 처음에 matrix를 입력 받을 때 r이 아닌 (r + 1)로 받아야지 IndexError가 발생하지 않는다.

 

풀이 로직 

- l, r, c 값을 입력 받은 다음 l 번씩 (r + 1)을 받아서 matrix를 입력받는다. 

- matrix 값 중에서 S와 E의 위치를 찾는다.

- S 위치를 시작으로 bfs를 진행한다. 

- 탐색은 행렬 범위 내에 방문하지 않았고 ' . ' 또는 'E' 값인 지점으로 하면 된다.

- visit[z][x][y]의 값을 기준으로 0이라면 S에서 E로 못간 것이므로 'Trapped!'를 출력해주고, 0이 아니라면 visit[z][x][y] - 1을 포함한 문장을 출력해준다. (S를 방문처리하기 위해 시작을 1로 했기에 정답과 1 차이가 나서 빼줬다)

 

정답 풀이 

- bfs 

def bfs(c, a, b, matrix, visit, z, x, y):
    visit[c][a][b] = 1
    queue = [[c, a, b]]
    dc, da, db = [-1, 1, 0, 0, 0, 0], [0, 0, -1, 1, 0, 0], [0, 0, 0, 0, -1, 1]
    e, f, g = len(matrix), len(matrix[0]), len(matrix[0][0])
    
    while queue:
        c, a, b = queue.pop(0)
        
        if c == z and a == x and b == y:
            return visit[z][x][y]
        
        for i in range(6):
            nc, na, nb = c + dc[i], a + da[i], b + db[i]
            if 0 <= nc < e and 0 <= na < f and 0 <= nb < g:
                if not visit[nc][na][nb] :
                    if (matrix[nc][na][nb] == '.' or matrix[nc][na][nb] == 'E'):
                        visit[nc][na][nb] = visit[c][a][b] + 1
                        queue.append([nc, na, nb])
                        
    return visit[z][x][y]

 

- 주어진 matrix 만들고 S 와 E의 위치 구하기 

while True:
    first, second, third = map(int, input().split())
    
    if first == 0 and second == 0 and third == 0:
        break
    
    c, a, b = 0, 0, 0
    z, x, y = 0, 0, 0
    matrix = [[] for _ in range(first)]
    for i in range(first):
        for j in range(second + 1): # 한 층 다음에 오는 빈칸 때문에 IndexError 계속 발생함
            temp = list(input())
            if len(temp) != 0:
                matrix[i].append(temp)
            else:
                continue
                 
    times = 0
    for i in range(first):
        for j in range(second):
            for k in range(third):
                if times == 2:
                    break
                if matrix[i][j][k] == 'S':
                    c, a, b = i, j, k # z, x, y
                    times += 1
                if matrix[i][j][k] == 'E':
                    z, x, y = i, j, k
                    times += 1

 

- 전체 코드 

def bfs(c, a, b, matrix, visit, z, x, y):
    visit[c][a][b] = 1
    queue = [[c, a, b]]
    dc, da, db = [-1, 1, 0, 0, 0, 0], [0, 0, -1, 1, 0, 0], [0, 0, 0, 0, -1, 1]
    e, f, g = len(matrix), len(matrix[0]), len(matrix[0][0])
    
    while queue:
        c, a, b = queue.pop(0)
        
        if c == z and a == x and b == y:
            return visit[z][x][y]
        
        for i in range(6):
            nc, na, nb = c + dc[i], a + da[i], b + db[i]
            if 0 <= nc < e and 0 <= na < f and 0 <= nb < g:
                if not visit[nc][na][nb] :
                    if (matrix[nc][na][nb] == '.' or matrix[nc][na][nb] == 'E'):
                        visit[nc][na][nb] = visit[c][a][b] + 1
                        queue.append([nc, na, nb])
                        
    return visit[z][x][y]                   
    
while True:
    first, second, third = map(int, input().split())
    
    if first == 0 and second == 0 and third == 0:
        break
    
    c, a, b = 0, 0, 0
    z, x, y = 0, 0, 0
    matrix = [[] for _ in range(first)]
    for i in range(first):
        for j in range(second + 1): # 한 층 다음에 오는 빈칸 때문에 IndexError 계속 발생함
            temp = list(input())
            if len(temp) != 0:
                matrix[i].append(temp)
            else:
                continue
                 
    times = 0
    for i in range(first):
        for j in range(second):
            for k in range(third):
                if times == 2:
                    break
                if matrix[i][j][k] == 'S':
                    c, a, b = i, j, k # z, x, y
                    times += 1
                if matrix[i][j][k] == 'E':
                    z, x, y = i, j, k
                    times += 1   
    
    visit = [[[0] * third for _ in range(second)] for _ in range(first)]
    answer = bfs(c, a, b, matrix, visit, z, x, y)
    
    if answer == 0:
        print('Trapped!')
    else:
        print('Escaped in ' + str(answer - 1) + ' minute(s).')

 

삽질한 기록,,,

- 문제 : https://www.acmicpc.net/problem/5014

 

문제 이해 

- 1 부터 building 까지의 범위 안에서 current에서 company로 이동하는 최소 칸 수를 출력하는 문제다. 

- 이동은 한 번에 +u 또는 -d로 진행된다. 

 

풀이 로직 

- 입력값들을 받은 다음 arr를 설정해준다. 

- queue를 가지고 bfs를 진행하는데 현재 있는 노드가 company라면 while문을 종료한다. 

- 현재 있는 노드가 company가 아니라면 u와 d로 이동하면서 범위 내의 방문하지 않은 노드들 위주로 탐색한다.

- 이동하면서 이전에 방문하지 않은 노드들을 탐색하면서 이전 노드의 값 + 1(arr[x] + 1)로 업데이트 해준다. 

- 반복문이 종료된 뒤 arr[company] 값에 따라 출력을 다르게 해주면 된다.

 

정답 풀이 

고려하지 않아도 될 상황을 고려해서 시간초과가 많이 발생했는데, 이 문제는 단순 bfs로 풀면 되기 때문에 방문하지 않은 노드들에 대해서만 진행하면 된다.

building, current, company, u, d = map(int, input().split())

arr = [0] * (building + 1)
arr[current] = 1
queue = [current]
while queue:
    x = queue.pop(0)
    
    if x == company:
        break
        
    for nx in [x + u, x - d]:
        if 1 <= nx <= building :
            if not arr[nx]:
                arr[nx] = arr[x] + 1
                queue.append(nx)
            
if arr[company] == 0:
    print("use the stairs")
else:
    print(arr[company] - 1)

+ Recent posts