Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

13-SeongHoonC #49

Merged
merged 1 commit into from
Mar 7, 2024
Merged

13-SeongHoonC #49

merged 1 commit into from
Mar 7, 2024

Conversation

SeongHoonC
Copy link
Collaborator

@SeongHoonC SeongHoonC commented Mar 3, 2024

🔗 문제 링크

쉬운 최단거리

✔️ 소요된 시간

1시간 30분

graph 하나만 써서 해보려고 했는데 포기하고 visited 배열 하나 더 생성해서 푼다고 시간이 오래걸렸네용

✨ 수도 코드

  1. 시작하는 좌표를 0으로 만들고 큐에 넣어서 시작합니다.
  2. bfs 로 탐색하면서 +1 합니다.
  3. 벽(0)이면 가지 않습니다.
  4. 이미 탐색한 곳이면 가지 않습니다.
  5. 처음 탐색하면 이전 좌표에서 + 1 한 값으로 graph 를 업데이트하고 visited = true, q 에 push 합니다.
val dx = listOf(1, -1, 0, 0)
val dy = listOf(0, 0, 1, -1)

fun main() {
    val br = BufferedReader(InputStreamReader(System.`in`))
    val (n, m) = br.readLine().split(" ").map { it.toInt() }

    var start = 0 to 0
    val graph = Array(n) { Array(m) { 0 } }

    // 입력받기
    for (i in 0 until n) {
        val line = br.readLine().split(" ").map { it.toInt() }
        for (j in 0 until m) {
            // 시작점이면 0으로 만들기
            if (line[j] == 2) {
                start = i to j
                graph[i][j] = 0
                continue
            }
            graph[i][j] = line[j]
        }
    }

    val q = ArrayDeque<Pair<Int, Int>>()
    val visited = Array(n) { Array(m) { false } }
    q.add(start)

    while (q.isNotEmpty()) {
        val now = q.removeFirst()

        // 상 하 좌 우
        for (i in 0..3) {
            val nextX = now.first + dx[i]
            val nextY = now.second + dy[i]

            // 범위를 벗어나면
            if (nextX >= n || nextY >= m || nextX < 0 || nextY < 0) {
                continue
            }

            // 벽이면
            if (graph[nextX][nextY] == 0) {
                continue
            }

            // 이미 방문했다면
            if (visited[nextX][nextY]) {
                continue
            }

            // +1 해서 넣고 방문 체크 후 큐에 집어넣기
            graph[nextX][nextY] = graph[now.first][now.second] + 1
            visited[nextX][nextY] = true
            q.add(nextX to nextY)
        }
    }

    // 방문하지 않았고 벽이 아니라면 -1
    for (i in 0 until n) {
        for (j in 0 until m) {
            if (visited[i][j] || graph[i][j] == 0) {
                continue
            }
            graph[i][j] = -1
        }
    }

    for (i in 0 until n) {
        println(graph[i].joinToString(" "))
    }
}

📚 새롭게 알게된 내용

@9kyo-hwang
Copy link

9kyo-hwang commented Mar 4, 2024

Visited 배열 대신 거리 기록용 Distances 배열을 이용하는 것도 괜찮아 보이네요.

  • $-1$로 초기화된 배열
  • 시작 좌표는 0으로 설정
  • 주어진 지도에서 애초에 갈 수 없는 좌표도 0으로 설정

이 상태에서 BFS를 수행하며 원본 지도는 건드리지 않고 단순히 "갈 수 있는 지" 검사하는 용도로만 사용하는 겁니다. 방문 체크의 경우 Distances 배열의 값이 -1이 아니면 이전에 방문했음을 알 수 있으니까 해결 가능합니다.

from collections import deque
input = open(0).readline

n, m = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(n)]
distances = [[-1] * m for _ in range(n)]  # 초기값은 -1
q = deque()

for i in range(n):
    for j in range(m):
        if board[i][j] == 2:  # 시작점
            distances[i][j] = 0
            q.append((i, j))
        elif board[i][j] == 0:  # 갈 수 없는 영역
            distances[i][j] = 0
            
offset = [(-1, 0), (0, 1), (1, 0), (0, -1)]

def out_of_bound(x: int, y: int) -> int:
    return not (0 <= x < n and 0 <= y < m)
    
while q:
    x, y = q.popleft()
    
    for dx, dy in offset:
        nx, ny = x + dx, y + dy
        # 범위를 벗어났거나, 갈 수 있는 곳이 아니거나, 이미 방문했던 곳이라면 가지 않음
        if out_of_bound(nx, ny) or board[nx][ny] != 1 or distances[nx][ny] != -1:
            continue
        
        distances[nx][ny] = distances[x][y] + 1  # (x, y)에서 한 칸 더 감
        q.append((nx, ny))
        
print('\n'.join([' '.join(map(str, row)) for row in distances]))  # distances 배열에 담긴 값 모두 출력

@SeongHoonC SeongHoonC removed the request for review from fnzksxl March 5, 2024 04:44
@alstjr7437
Copy link
Member

저도 그래프를 visited를 따로 만들지 않고 위에 교황님이 말했던 것 처럼

  1. -1로 다 저장을 해두고 거리를 갱신했습니다.
  2. 마지막에 출력 부분에서 graph를 확인해서 못가는 벽으로 된 곳이면 0을 출력하도록 했습니다!!
    그러면 못가는 부분도 -1로 출력해서 되더라구요!!
from collections import deque

dx = [0,0,-1,1]
dy = [1,-1,0,0]

n, m = map(int, input().split())

graph = []
visited = [[-1] * m for _ in range(n)]

for _ in range(n):
    graph.append(list(map(int, input().split())))

for i in range(n):
    for j in range(m):
        if graph[i][j] == 2:
            first_x,first_y = j, i

queue = deque()
queue.append([first_x, first_y])
visited[first_y][first_x] = 0

while queue:
    x, y = queue.popleft()
    for i in range(4):
        nx, ny = x + dx[i], y + dy[i]

        if nx >= m or nx < 0 or ny >= n or ny < 0:
            continue

        if visited[ny][nx] == -1 and graph[ny][nx] == 1:
            visited[ny][nx] = visited[y][x] + 1
            queue.append([nx,ny])

for i in range(n):
    for j in range(m):
        if graph[i][j] == 0:
            print(0, end = " ")
        else : 
            print(visited[i][j], end =" ")
    print()

Copy link
Collaborator

@wkdghdwns199 wkdghdwns199 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from collections import deque
import sys
input = sys.stdin.readline

N,M = map(int, input().split())
queue = deque()
_map = []
visited = [[False] * M for _ in range(N)]
result = [[-1]*M for _ in range(N)]

for i in range(N):
    row = list(map(int, input().split()))
    for j in range(M):
        if row[j] == 2 :
            queue.append((i,j))
            visited[i][j] = True
            result[i][j] = 0
        if row[j] == 0 :
            result[i][j] = 0
    _map.append(row)

direction = [(1,0), (-1,0), (0,1), (0,-1)]
while queue :
    x,y = queue.popleft()
    for dx, dy in direction :
        move_x, move_y = x+dx, y+dy
        if 0<=move_x < N and 0<=move_y < M and visited[move_x][move_y] == False and _map[move_x][move_y] :
            queue.append((move_x, move_y))
            visited[move_x][move_y] = True
            result[move_x][move_y] = result[x][y] + 1

for row in result :
    for i in row :
        print (i, end=' ')
    print()

BFS 문제 더욱 많이 풀어봐야겠어요..! 이 문제 풀어보면서 헷갈렸던 부분이 어떤 조건에서 queue를 집어넣어야 하는지 였습니다.

@SeongHoonC SeongHoonC merged commit 46d20c9 into main Mar 7, 2024
7 checks passed
@SeongHoonC SeongHoonC deleted the 13-SeongHoonC branch March 7, 2024 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants