파이썬 알고리즘 3주차 BFS : 특정 거리의 도시 찾기, 미로 탐색

정글일지 16

1.개발 진행 및 완료상황

  • 2주차 python algorithm bfs 문제 풀이 중
  • CSAPP 2주차 목표 읽기 완료
  • 업무, 개발 중 발생한 이슈/고민 또는 이를 해결한 내용

  • 백준 18352

18352번: 특정 거리의 도시 찾기

문제 어떤 나라에는 1번부터 N 번까지의 도시와 M 개의 단방향 도로가 존재한다. 모든 도로의 거리는 1이다. 이 때 특정한 도시 X 로부터 출발하여 도달할 수 있는 모든 도시 중에서, 최단 거리가 정확히 K 인 모든 도시들의 번호를 출력하는 프로그램을 작성하시오. 또한 출발 도시 X 에서 출발 도시 X 로 가는 최단 거리는 항상 0이라고 가정한다. 예를 들어 N =4, K =2, X =1일 때 다음과 같이 그래프가 구성되어 있다고 가정하자. 이 때 1번 도시에서 출발하여 도달할 수 있는 도시 중에서, 최단 거리가 2인 도시는 4…

www.acmicpc.net

풀이 과정 : 일반적으로 볼 수 있는 BFS문제였다.하지만 여전히 특정 값을 추출해 내는 과정을 어려워하는 내 입장에선 까다로웠다. 다음 도시로 탐색할때마다 특정 변수를 +1 해주는 것까진 설정할 수 있었으나, 그걸 적절한 과정에서 추출해 내는 것이 힘들었다. 꾸준한 연습이 필요하다.

정답 코드 :

import sys from collections import deque n,m,k,x = map(int,sys.stdin.readline().split()) graph= [[] for _ in range(n+1)] ans = [0](n+1) visited_bfs = [0](n+1) for _ in range(m): a,b = map(int,sys.stdin.readline().split()) graph[a].append(b) def bfs(x): data = [] queue = deque([x]) visited_bfs[x] = 1 ans[x] = 0 while queue: y = queue.popleft() for i in graph[y]: if visited_bfs[i] == 0: visited_bfs[i] = 1 queue.append(i) ans[i] = ans[y] + 1 if ans[i] == k: data.append(i) if len(data) == 0: print(-1) else: data.sort() for i in data: print(i, end=’\n’) bfs(x)

  • 백준 2178

2178번: 미로 탐색

문제 N×M크기의 배열로 표현되는 미로가 있다. 1 0 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다. 위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 …

www.acmicpc.net

풀이 과정 : 각각 경로마다 행,열의 값의 변화를 리스트로 만들었다. 따라서 동서남북으로 움직일 때마다 변화를 동일한 index 값을 리스트에 부여하는 방법으로 코드를 구성했다. 변화 결과 고려할 필요가 없는 곳으로 이동하는 경우를 조건문으로 제거했다.

정답 코드

import sys from collections import deque n, m = map(int, sys.stdin.readline().split()) graph = [] for _ in range(n): graph.append(list(map(int, sys.stdin.readline().rstrip()))) def bfs(a, b): row_move = [1, 0, -1, 0] col_move = [0, -1, 0, 1] queue = deque() queue.append((a, b)) while queue: a, b = queue.popleft() for i in range(4): aa = a + row_move[i] bb = b + col_move[i] if aa > n-1 or aa < 0 or bb > m-1 or bb < 0: continue if graph[aa][bb] == 1: graph[aa][bb] = graph[a][b] + 1 queue.append([aa, bb]) return graph[n-1][m-1] ans = bfs(0, 0) print(ans)

  1. 새로 배운 내용
  • 그래프의 이해

    정의 : 실제 사물이나 현상을 정점(Vertex), 노드(Node), 간선(Edge)으로 표현하기 위해 사용 되는 컴퓨터 프로그래밍 개념

관련 개념 및 용어 정리

  1. 노드(Node) : 위치. 원으로 표현되며, 정점(Vertex)라고도 표현
  2. 간선(Edge) : 위치 간 관계를 표시한 선으로, 노드 간 연결 선. 간선에는 방향성이 있을 수도, 없을 수도 있음
  3. 인접 정점(Adjacent Vertex) : 간선으로 직접 연결된 정점 또는 노드를 의미
  4. 기타
  5. 정점의 차수(degree) : 무방향 그래프에서 하나의 정점에 인접한 정점의 수
  6. 진입 사추(In-degree) : 방향 그래프에서 외부에서 오는 간선의 수
  7. 진출 차수(out-degree) : 방향 그래프에서 외부로 향하는 간선의 수
  8. 경로의 길이(Path Length) : 경로를 구상하기 위해 사용된 간선의 수
  9. 단순 경로(simple path) : 처음 정점과 끝 정점을 제외하고, 중복된 정점이 없는 경로
  10. 사이클(Cycle) : 단순 경로의 시작 정점과 종료 정점이 동일한 경우

그래프의 종류

  1. 무방향 그래프(Undirected Graph)
  2. 정의 : 방향이 없는 그래프. 간선을 통해 노드는 양방향으로 이동 가능. 노드 간 관계를 (a,b) or (b,a)로 표시

  3. 방향 그래프(Directed Graph)
  4. 정의 : 간선에 방향이 있는 그래프로 표기할 때 <A,B>로 표시. <B,A>와 방향성이 다르기 때문에 다른 그래프

  5. 가중치 그래프(Weighted Graph) / 네트워크(Network)
  6. 정의 : 간선에 비용 또는 가중치가 할당된 그래프. 네트워크 이론 or 신경망 이론에 활용되는 기본 개념

  7. 연결 그래프(Connected Graph) 와 비연결 그래프(Disconnected Graph)
  • 연결 그래프(Connected Graph)
  1. 정의 : 무방향 그래프에 있는 모든 노드에 대해 항상 경로가 존재하는 경우를 의미
  • 비연결 그래프(Disconnected Graph)
  1. 정의 : 무방향 그래프에서 특정 노드에 대해 경로가 존재하지 않는 경우
  • 사이클(Cycle)과 비순환 그래프(Acyclic Graph)
  1. 사이클(Cycle) : 단순 경로의 시작 노드와 종료 노드가 동일한 경우
  2. 비순환 그래프(Acyclic Graph) : 사이클이 없는 그래프
  • 완전 그래프(Complete Graph)
  1. 정의 : 그래프의 모든 노드가 서로 연결되어 있는 그래프

그래프(Graph) VS 트리(Tree)

  1. 그래프(Graph)
  • 노드와 노드를 연결하는 간선
  • 방향 & 무방향 모두 가능
  • 사이클 비순환 모두 가능
  • 루트 노드 존재 X
  • 부모자식 개념 X
  1. 트리(Tree)
  • 그래프의 한 종류, 방향성이 있는 비순환 그래프
  • 방향이 고정
  • 비순환만 존재
  • 루트 노드 존재
  • 부모 자식 개념 존재

  • 그래프 알고리즘의 종류

MST(최소신장트리)

  • 크루스칼 : 간선기준 가장 작은것부터 연결, 음의 간선 가능
  • 프림 : 정점기준 정점에 연결된 가장 작은 간선으로 연결, 음의 간선 가능

간선 개수 적으면? => 크루스칼, 정점 개수 적으면? => 프림

최단경로

  • 다익스트라 (우선순위 큐 heapq 사용, 단일 정점 최단경로)
  • 벨만-포드 (음의 가중치, 경로 추적 가능)
  • 플로이드 와샬 (음의 가중치, 3중포문, 모든 정점 사이 최단거리)
  • SPFA (shortest path faster algorithm)
  1. 크루스칼
  • 간선을 정렬하여 가중치가 작은 간선부터 연결
  • 사이클이 발생하면 연결하지 않음
  • O(E * log))
  1. 프림
  • 한 정점의 간선 중 가중치가 가장 작은 간선과 연결된 정점 방문
  • O(E * log(V)) -> 우선순위 큐 사용시
  1. 플로이드 와샬
  • 모든 최단 경로를 구함
  • 출발 정점 따로 없음
  • 음의 가중치 간선 가능
  • 2차원의 배열 자료구조
  • 거쳐가는 정점을 기준으로 최단 거리를 구함
  • 3중 for문으로 모든 최단 경로 탐색
  • 시간복잡도 = O(V^3)
  • 공간복잡도 = O(V^2)
  1. 벨만-포드
  • 다익스트라의 조건에 음의 간선이 있다는 조건이 포함될 때 사용
  • 음수 가중치가 있는 그래프의 한 정점부터 다른 노드까지 최단 거리
  • 음수 사이클 존재 여부 확인 가능
  • 시간복잡도 = O(VE)
  • 다익스트라보다 느림
  • V번 반복하며 매 반복마다 모든 간선을 확인해 갱신
  1. 다익스트라
  • 한 정점으로부터 다른 정점까지의 최단 거리
  • O(E*log(V))
  • 양수 간선만 가능
  • 매 상황에서 가장 비용이 적은 노드 선택
  • 참고할 만한 레퍼런스들

  • 자료구조와 함께 배우는 알고리즘 입문 파이썬편(BohYoh Shibata 지음, 강민 옮김, 이지스 퍼블리싱)
  • https://data-marketing-bk.tistory.com/entry/%EA%B7%B8%EB%9E%98%ED%94%84%EC%9D%98-%EC%9D%B4%ED%95%B4-%EA%B3%A0%EB%8F%84-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90
  • https://cme10575.tistory.com/115?category=0
  • https://steadily-worked.tistory.com/646
  • https://jokerldg.github.io/algorithm/2021/03/24/maze.html
  • 특이사항

  • 한주의 시작이지만 바뀐건 없음.
  • 회고

  • BFS에 관한 문제를 풀다 각 문제 유형에 따른 다양한 알고리즘이 있음을 알게 됐다. 어떤 알고리즘이 있고 어떤 장단점과 특징이 있으며, 어떤 경우에 써야할 지에 대해 조금 더 자세한 공부가 필요하다. 또한 맞춘 문제라고 넘어가지 말고 각주를 통해 내가 어떤 생각으로 풀었었는지 꼭 적어놓자.
  • TO-DO-LIST
  1. 그래프 알고리즘 관련 개념 공부
  2. 3주차 파이썬 알고리즘 BFS 문제 풀이