[알고리즘] 미로 최단 경로 찾기 (finding the shortest path in a maze)
앞서 올렸던 미로 내 거리 계산 알고리즘의 upgrade version이며,
1. get a maze as input in form of an array
void graph_app_maze_distance() { uint32 maze[] = { 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, }; uint32 maze_width = 5; uint32 start_idx = 20; uint32 end_idx = 4; graph_app_get_maze_path( maze, get_length(maze, maze[0]), maze_width, start_idx, end_idx); } |
2. graph_app_get_maze_distance code
1) graph_app_maze_init_paths로 입력 array에서 ‘벽’이 아닌 ‘길’에 대해서만 path_item_t type의 instance array를 생성 후 리턴
2) items를 path item의 개수 만큼 할당
3) path item array를 graph 형태로 transform하여 graph를 형성함(items)
4) start index를 시작점으로 하여 미로 찾기를 시작
graph_bfs_nr: distance를 계산
graph_get_the_shortest_path: shortest path를 계산
graph_reverse_path: path를 reverse 시켜 시작부터 끝까지의 길을 기록
graph_app_find_distance: destination까지의 거리 출력
graph_trace_shortest_path: start 부터 destination까지의 shortest path 출력
void graph_app_get_maze_path(uint32 *maze, uint32 maze_len, uint32 maze_width, uint32 sidx, uint32 eidx) { uint32 num_kinds = 0, i, num_paths = 0; uint32 num_item = 0; item_t *items = NULL; char *start_coordinate = _graph_get_str_coordinate( sidx, maze_width); char *end_coordinate = _graph_get_str_coordinate( sidx, maze_width);
for (i = 0; i < maze_len; i++) num_paths++; path_item_t *paths = graph_app_maze_init_paths( maze, maze_len, num_paths, maze_width, num_item); items = (item_t *)mem_alloc(sizeof(item_t)*num_item); memset(items, 0, sizeof(item_t)*num_item); graph_app_transform_path_into_graph( items, paths, maze_len, maze_width, num_item); int start_idx = item_find_slot( items, start_coordinate, num_item); if (-1 != start_idx) { stack<u32> visit_history = graph_bfs_nr( items, num_item, start_idx); stack<u32> reversed_path = graph_get_the_shortest_path( items, visit_history, num_item); queue<u32> shortest_path = graph_reverse_path(reversed_path); graph_app_find_distance(items, end_coordinate, num_item); graph_trace_shortest_path(items, shortest_path); } else { LOGD("WRONG IDX\r\n"); } ... } |
3. BFS
BFS code is coded in non-recursive manner but it uses a queue in order to cover up.
(as you know, code in recursive is more simple and easy to see, but I used a queue to prevent stack overflow problem)
stack<u32> graph_bfs_nr(item_t *items, uint32 n, uint32 start_idx) { uint32 i, j; stack<u32> visit_history; queue<long> idx_que; queue<long> que; uint32 pos, distance; adj_node_t *adj_node; list_node_t *node; for (i = 0; i < n; i++) { items[i].visited = false; items[i].distance = 0; } uint32 nums = n; idx_que.push(start_idx); nums--; i = 0; while (nums) { if (i != start_idx) idx_que.push(i); nums--; i++; } while (!idx_que.empty()) { i = idx_que.front(); idx_que.pop(); if (true == items[i].visited) continue; que.push(i); items[i].visited = true; items[i].distance = 0; while (!que.empty()) { j = que.front(); que.pop(); distance = items[j].distance; LOGD("%s(%u) -> ", items[j].vertex.name, distance); visit_history.push(j); if (RET_TYPE_FAILURE == items[j].adj_list->get_head_position( items[j].adj_list, &pos)) continue; while (1) { node = items[j].adj_list->get_next( items[j].adj_list, &pos); if (NULL == node) break; adj_node = (adj_node_t *)node->data; int k = item_find_slot( items, adj_node->vertex->name, n); if (false == items[k].visited) { items[k].distance = distance + 1; items[k].visited = true; que.push(k); } } } } return visit_history; } |
'Algorithms' 카테고리의 다른 글
Softeer: 징검다리2 (0) | 2021.12.22 |
---|---|
[알고리즘] 위상정렬 코드 (topological sort) for DAG (Directed acyclic graph) (0) | 2018.03.18 |
[알고리즘] graph cycle 여부 판단 알고리즘 (undirected 용) (0) | 2015.07.05 |
[알고리즘] 개미집 찾기 문제 (한 node가 다른 node 의 탐색 경로 내 존재 여부 찾기) (0) | 2015.07.04 |
[알고리즘] dynamic Fibonacci (0) | 2015.07.04 |
댓글