ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ AใฎๅฎŸ่ฃ…*



ใ“ใฎ่จ˜ไบ‹ใฏใ€A *ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎ็ดนไป‹ใฎ็ถšใใงใ™ ใ€‚ ใใฎไธญใงใ€ๅน…ๅ„ชๅ…ˆๆคœ็ดขใ€ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ€ๆœ€้ฉใชๆœ€ๅˆใฎไธ€่‡ดใ‚’ๆฑ‚ใ‚ใ‚‹่ฒชๆฌฒใชๆคœ็ดขใ€ใŠใ‚ˆใณA *ใฎๅฎŸ่ฃ…ๆ–นๆณ•ใ‚’็คบใ—ใพใ—ใŸใ€‚ ่ชฌๆ˜Žใ‚’ใงใใ‚‹้™ใ‚Š็ฐก็ด ๅŒ–ใ—ใ‚ˆใ†ใจใ—ใพใ—ใŸใ€‚

ใ‚ฐใƒฉใƒ•ๆคœ็ดขใฏใ€้กžไผผใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎใƒ•ใ‚กใƒŸใƒชใƒผใงใ™ใ€‚ ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใจใใฎๅฎŸ่ฃ…ใซใฏๅคšใใฎใƒใƒชใ‚จใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ™ใ€‚ ใ“ใฎ่จ˜ไบ‹ใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎๆœ€็ต‚ใƒใƒผใ‚ธใƒงใƒณใงใฏใชใใ€ใ™ในใฆใฎ็Šถๆณใซ้ฉใ—ใŸ้–‹ๅง‹็‚นใจใ—ใฆๆ‰ฑใ„ใพใ™ใ€‚

1. PythonใฎๅฎŸ่ฃ…


ไปฅไธ‹ใงใฏใ€ใปใจใ‚“ใฉใฎใ‚ณใƒผใƒ‰ใซใคใ„ใฆ่ชฌๆ˜Žใ—ใพใ™ใ€‚ implementation.pyใƒ•ใ‚กใ‚คใƒซใฏๅฐ‘ใ—ๅบƒใใชใฃใฆใ„ใพใ™ใ€‚ ใ‚ณใƒผใƒ‰ใฏPython 3ใ‚’ไฝฟ็”จใ™ใ‚‹ใŸใ‚ใ€Python 2ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฏใ€ๅ‘ผใณๅ‡บใ—ใ‚’super()ใซๅค‰ๆ›ดใ—ใ€ print้–ขๆ•ฐใ‚’Python 2ใฎ้กžไผผ็‰ฉใซๅค‰ๆ›ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

1.1ใƒฏใ‚คใƒ‰ๆคœ็ดข


Pythonใงๅน…ๅ„ชๅ…ˆๆคœ็ดขใ‚’ๅฎŸ่ฃ…ใ—ใพใ—ใ‚‡ใ†ใ€‚ ๆœ€ๅˆใฎ่จ˜ไบ‹ใงใฏใ€ๆคœ็ดขใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎPythonใ‚ณใƒผใƒ‰ใ‚’็คบใ—ใฆใ„ใพใ™ใŒใ€ไฝฟ็”จใ™ใ‚‹ใ‚ฐใƒฉใƒ•ใ‚’ๆฑบๅฎšใ™ใ‚‹ๅฟ…่ฆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ ็งใŒไฝฟ็”จใ™ใ‚‹ใ„ใใคใ‹ใฎๆŠฝ่ฑกๅŒ–ใ‚’ไปฅไธ‹ใซ็คบใ—ใพใ™ใ€‚

ใ‚ฐใƒฉใƒ• ๏ผšๅ„ใƒใ‚คใƒณใƒˆใฎ่ฟ‘ๅ‚ใ‚’ใƒฌใƒใƒผใƒˆใงใใ‚‹ใƒ‡ใƒผใ‚ฟๆง‹้€ ๏ผˆ ใ“ใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’ๅ‚็…ง๏ผ‰

ใƒใ‚คใƒณใƒˆ๏ผˆๅ ดๆ‰€๏ผ‰ ๏ผšใ‚ฐใƒฉใƒ•ๅ†…ใฎใƒใ‚คใƒณใƒˆใ‚’ใƒžใƒผใ‚ฏใ™ใ‚‹ๅ˜็ด”ใชๅ€ค๏ผˆintใ€stringใ€tupleใชใฉ๏ผ‰

ๆคœ็ดข ๏ผšใ‚ฐใƒฉใƒ•ใ€้–‹ๅง‹็‚นใ€ใŠใ‚ˆใณ๏ผˆใ‚ชใƒ—ใ‚ทใƒงใƒณใง๏ผ‰ไธ€้ƒจใพใŸใฏใ™ในใฆใฎ็‚นใฎๆœ‰็”จใชๆƒ…ๅ ฑ๏ผˆ่จชๅ•ใ€่ฆช่ฆ็ด ใธใฎใƒใ‚คใƒณใ‚ฟใƒผใ€่ท้›ข๏ผ‰ใ‚’่จˆ็ฎ—ใ™ใ‚‹็ต‚ไบ†็‚นใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ 

ใ‚ญใƒฅใƒผ ๏ผšๆคœ็ดขใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใŒใƒใ‚คใƒณใƒˆใฎๅ‡ฆ็†้ †ๅบใ‚’้ธๆŠžใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ใƒ‡ใƒผใ‚ฟๆง‹้€ ใ€‚

ๆœ€ๅˆใฎ่จ˜ไบ‹ใงใฏใ€็งใฏไธปใซๆคœ็ดขใซใคใ„ใฆ่ฆ‹ใฆใใพใ—ใŸใ€‚ ใ“ใฎ่จ˜ไบ‹ใงใฏใ€ๅฎŒๅ…จใซๆฉŸ่ƒฝใ™ใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชไป–ใฎใ™ในใฆใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ ใ‚ฐใƒฉใƒ•ใ‹ใ‚‰ๅง‹ใ‚ใพใ—ใ‚‡ใ†๏ผš

 class SimpleGraph: def __init__(self): self.edges = {} def neighbors(self, id): return self.edges[id] 

ใฏใ„ใ€ๅฟ…่ฆใชใฎใฏใใ‚Œใ ใ‘ใงใ™๏ผ ใ‚ใชใŸใฏๅฐ‹ใญใ‚‹ใ“ใจใŒใงใใพใ™๏ผšใƒŽใƒผใƒ‰ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆใƒŽใƒผใƒ‰๏ผ‰ใฏใฉใ“ใงใ™ใ‹๏ผŸ ๅ›ž็ญ”๏ผšใƒŽใƒผใƒ‰ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏใปใจใ‚“ใฉไฝฟ็”จใ—ใพใ›ใ‚“ใ€‚ ๆ•ดๆ•ฐใ€ๆ–‡ๅญ—ๅˆ—ใ€ใพใŸใฏใ‚ฟใƒ—ใƒซใ‚’ใƒใ‚คใƒณใƒˆใจใ—ใฆไฝฟ็”จใ—ใ€้…ๅˆ—ใพใŸใฏใƒใƒƒใ‚ทใƒฅใƒ†ใƒผใƒ–ใƒซใ‚’ไฝฟ็”จใ—ใฆใƒใ‚คใƒณใƒˆใ‚’ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใจใ—ใฆไฝฟ็”จใ™ใ‚‹ๆ–นใŒ็ฐกๅ˜ใชใ‚ˆใ†ใงใ™ใ€‚

ใ‚จใƒƒใ‚ธใซใฏๆ–นๅ‘ใŒใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„๏ผšAใ‹ใ‚‰Bใฎใ‚จใƒƒใ‚ธใ‚’ไฝฟ็”จใงใใพใ™ใŒใ€Bใ‹ใ‚‰Aใฎใ‚จใƒƒใ‚ธใฏไฝฟ็”จใงใใพใ›ใ‚“ใ€‚ใ‚ฒใƒผใƒ ใ‚ซใƒผใƒ‰ใงใฏใ€ใ‚จใƒƒใ‚ธใฏไธปใซๅŒๆ–นๅ‘ใงใ™ใŒใ€ๅ ดๅˆใซใ‚ˆใฃใฆใฏไธ€ๆ–นๅ‘ใฎใƒ‰ใ‚ขใพใŸใฏๆฃšใ‹ใ‚‰ใฎใ‚ธใƒฃใƒณใƒ—ใŒใ‚ใ‚Šใ€ใ“ใ‚Œใฏๆœ‰ๅ‘ใ‚จใƒƒใ‚ธใจใ—ใฆๆŒ‡ๅฎšใ•ใ‚Œใพใ™ใ€‚ ใƒใ‚คใƒณใƒˆใŒๆ–‡ๅญ—AEใง็คบใ•ใ‚Œใ‚‹ใ‚ฐใƒฉใƒ•ใฎไพ‹ใ‚’ไฝœๆˆใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚



ๅ„ใƒใ‚คใƒณใƒˆใซใคใ„ใฆใ€ใใ‚ŒใŒๅฐŽใใƒใ‚คใƒณใƒˆใฎใƒชใ‚นใƒˆใŒๅฟ…่ฆใงใ™ใ€‚

 example_graph = SimpleGraph() example_graph.edges = { 'A': ['B'], 'B': ['A', 'C', 'D'], 'C': ['A'], 'D': ['E', 'A'], 'E': ['B'] } 

ๆคœ็ดขใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ‰ใซใ€ ใ‚ญใƒฅใƒผใ‚’่จญๅฎšใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ ใ€‚

 import collections class Queue: def __init__(self): self.elements = collections.deque() def empty(self): return len(self.elements) == 0 def put(self, x): self.elements.append(x) def get(self): return self.elements.popleft() 

ใ“ใฎใ‚ญใƒฅใƒผใ‚ฏใƒฉใ‚นใฏใ€็ต„ใฟ่พผใฟใฎcollections.dequeใ‚ฏใƒฉใ‚นใฎๅ˜ใชใ‚‹ใƒฉใƒƒใƒ‘ใƒผใงใ™ใ€‚ ใ‚ณใƒผใƒ‰ใงdeque็›ดๆŽฅไฝฟ็”จใงใใพใ™ใ€‚

ใ“ใฎใ‚ญใƒฅใƒผใจๅ‰ใฎ่จ˜ไบ‹ใฎๅน…ๅ„ชๅ…ˆใฎๆคœ็ดขใ‚ณใƒผใƒ‰ใงใ‚ฐใƒฉใƒ•ใฎไพ‹ใ‚’ไฝฟ็”จใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚

 from implementation import * def breadth_first_search_1(graph, start): #  ,    frontier = Queue() frontier.put(start) visited = {} visited[start] = True while not frontier.empty(): current = frontier.get() print("Visiting %r" % current) for next in graph.neighbors(current): if next not in visited: frontier.put(next) visited[next] = True breadth_first_search_1(example_graph, 'A') 

Visiting 'A'
Visiting 'B'
Visiting 'C'
Visiting 'D'
Visiting 'E'


ใ‚ฐใƒชใƒƒใƒ‰ใฏใ‚ฐใƒฉใƒ•ใจใ—ใฆ่กจ็พใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ๆฌกใซใ€ใ‚ฟใƒ—ใƒซใฎ๏ผˆintใ€int๏ผ‰ ใƒใ‚คใƒณใƒˆใ‚’ไฝฟ็”จใ—ใฆใ€ๆ–ฐใ—ใ„SquareGrid ใ‚ฐใƒฉใƒ•ใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ ใ‚จใƒƒใ‚ธใ‚’ๆ˜Ž็คบ็š„ใซไฟๅญ˜ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€ neighbors้–ขๆ•ฐใงใ‚จใƒƒใ‚ธใ‚’่จˆ็ฎ—ใ—ใพใ™ใ€‚

 class SquareGrid: def __init__(self, width, height): self.width = width self.height = height self.walls = [] def in_bounds(self, id): (x, y) = id return 0 <= x < self.width and 0 <= y < self.height def passable(self, id): return id not in self.walls def neighbors(self, id): (x, y) = id results = [(x+1, y), (x, y-1), (x-1, y), (x, y+1)] if (x + y) % 2 == 0: results.reverse() #   results = filter(self.in_bounds, results) results = filter(self.passable, results) return results 

ๅ‰ใฎ่จ˜ไบ‹ใฎๆœ€ๅˆใฎใ‚ฐใƒชใƒƒใƒ‰ใงใƒ†ใ‚นใƒˆใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚

 from implementation import * g = SquareGrid(30, 15) g.walls = DIAGRAM1_WALLS #  long, [(21, 0), (21, 2), ...] draw_grid(g) 

. . . . . . . . . . . . . . . . . . . . . ####. . . . . . .
. . . . . . . . . . . . . . . . . . . . . ####. . . . . . .
. . . . . . . . . . . . . . . . . . . . . ####. . . . . . .
. . . ####. . . . . . . . . . . . . . . . ####. . . . . . .
. . . ####. . . . . . . . ####. . . . . . ####. . . . . . .
. . . ####. . . . . . . . ####. . . . . . ##########. . . .
. . . ####. . . . . . . . ####. . . . . . ##########. . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . . . . . . . . . . . ####. . . . . . . . . . . . . . .
. . . . . . . . . . . . . ####. . . . . . . . . . . . . . .
. . . . . . . . . . . . . ####. . . . . . . . . . . . . . .


ใƒ‘ใ‚นใ‚’ๅ†ไฝœๆˆใ™ใ‚‹ใซใฏใ€ๅ…ƒใฎใƒใ‚คใƒณใƒˆใ‚’ไฟๅญ˜ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใ€ visited ๏ผˆTrue / False๏ผ‰ใ‚’came_from ๏ผˆpoint๏ผ‰ใซๅค‰ๆ›ดใ—ใพใ—ใŸใ€‚

 from implementation import * def breadth_first_search_2(graph, start): #  "came_from" frontier = Queue() frontier.put(start) came_from = {} came_from[start] = None while not frontier.empty(): current = frontier.get() for next in graph.neighbors(current): if next not in came_from: frontier.put(next) came_from[next] = current return came_from g = SquareGrid(30, 15) g.walls = DIAGRAM1_WALLS parents = breadth_first_search_2(g, (8, 7)) draw_grid(g, width=2, point_to=parents, start=(8, 7)) 

โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† โ† ####โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†’ โ†‘ ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† โ† โ† ####โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†‘ โ†‘ ####โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† ####โ†‘ โ† โ† โ† โ† โ† ####โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“
โ†‘ โ†‘ โ†‘ ####โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ† โ† ####โ†‘ โ†‘ โ† โ† โ† โ† ##########โ†“ โ†“ โ†“ โ†
โ†‘ โ†‘ โ†‘ ####โ†’ โ†’ โ†’ โ†“ โ†“ โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ† โ† โ† ##########โ†“ โ†“ โ† โ†
โ†‘ โ†‘ โ†‘ ####โ†’ โ†’ โ†’ A โ† โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ ####โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ ####โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ†
โ†’ โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ†
โ†’ โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ†
โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ†
โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ†


ไธ€้ƒจใฎๅฎŸ่ฃ…ใงใฏใ€Nodeใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใซใ‚ˆใ‚Šใ€ใ‚ฐใƒฉใƒ•ๅ†…ใฎๅ„ใƒŽใƒผใƒ‰ใฎcame_fromใŠใ‚ˆใณใใฎไป–ใฎๅ€คใ‚’ๆ ผ็ดใ™ใ‚‹ใŸใ‚ใซๅ†…้ƒจใ‚นใƒˆใƒฌใƒผใ‚ธใŒไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ ไปฃใ‚ใ‚Šใซใ€ ๅค–้ƒจใ‚นใƒˆใƒฌใƒผใ‚ธใ‚’ไฝฟ็”จใ—ใฆใ€ใ‚ฐใƒฉใƒ•ๅ†…ใฎใ™ในใฆใฎใƒŽใƒผใƒ‰ใ‹ใ‚‰came_fromใ‚’ๆ ผ็ดใ™ใ‚‹ๅ˜ไธ€ใฎใƒใƒƒใ‚ทใƒฅใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใซใ—ใพใ—ใŸใ€‚ ใƒžใƒƒใƒ—ไธŠใฎใƒใ‚คใƒณใƒˆใซๆ•ดๆ•ฐใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๅˆฅใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ™-้…ๅˆ—ใ‚’ไฝฟ็”จใ—ใฆcame_fromใ‚’ๆ ผ็ดใ—came_from ใ€‚

1.2ๆ—ฉๆœŸ้€€ๅ‡บ


ๅ‰ใฎ่จ˜ไบ‹ใฎใ‚ณใƒผใƒ‰ใ‚’็นฐใ‚Š่ฟ”ใ—ใฆใ€ใƒกใ‚คใƒณใƒซใƒผใƒ—ใซifใ‚ณใƒณใ‚นใƒˆใƒฉใ‚ฏใƒˆใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚ ใ“ใฎใƒใ‚งใƒƒใ‚ฏใฏๅน…ๅ„ชๅ…ˆๆคœ็ดขใจใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใงใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ™ใŒใ€ๆœ€้ฉใชๆœ€ๅˆใฎไธ€่‡ดใจA *ใฎ่ฒชๆฌฒใชๆคœ็ดขใงใฏๅฟ…้ ˆใงใ™ใ€‚

 from implementation import * def breadth_first_search_3(graph, start, goal): frontier = Queue() frontier.put(start) came_from = {} came_from[start] = None while not frontier.empty(): current = frontier.get() if current == goal: break for next in graph.neighbors(current): if next not in came_from: frontier.put(next) came_from[next] = current return came_from g = SquareGrid(30, 15) g.walls = DIAGRAM1_WALLS parents = breadth_first_search_3(g, (8, 7), (17, 2)) draw_grid(g, width=2, point_to=parents, start=(8, 7), goal=(17, 2)) 

. โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† . . . . ####. . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† . . . ####. . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† Z . . . ####. . . . . . .
โ†’ โ†’ โ†‘ ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† . . ####. . . . . . .
. โ†‘ โ†‘ ####โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† ####โ†‘ โ† โ† . . . ####. . . . . . .
. . โ†‘ ####โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ† โ† ####โ†‘ โ†‘ . . . . ##########. . . .
. . . ####โ†’ โ†’ โ†’ โ†“ โ†“ โ† โ† โ† ####โ†‘ . . . . . ##########. . . .
. . . ####โ†’ โ†’ โ†’ A โ† โ† โ† โ† ####. . . . . . . . . . . . . . .
. . . ####โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ† โ† โ† ####. . . . . . . . . . . . . . .
. . โ†“ ####โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† ####. . . . . . . . . . . . . . .
. โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† ####. . . . . . . . . . . . . . .
โ†’ โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .
. โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .


ใ”่ฆงใฎใจใŠใ‚Šใ€ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏใ‚ฟใƒผใ‚ฒใƒƒใƒˆZ่ฆ‹ใคใ‘ใ‚‹ใจๅœๆญขใ—Z

1.3ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ 


ใ“ใ‚Œใฏใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎ่ค‡้›‘ใ•ใ‚’ๅข—ใ—ใพใ™ใ€‚ใ€Œๅ…ˆ็€้ †ใ€ใ ใ‘ใงใชใใ€ๆ”นๅ–„ใ•ใ‚ŒใŸ้ †ๅบใงใƒใ‚คใƒณใƒˆใฎๅ‡ฆ็†ใ‚’้–‹ๅง‹ใ™ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ ใฉใฎๅŽŸๅ‰‡ใ‚’ไฝฟ็”จใ—ใพใ™ใ‹๏ผŸ

  1. ใ‚ซใ‚ฆใƒณใƒˆใฏ็งปๅ‹•ใฎใ‚ณใ‚นใƒˆใ‚’็Ÿฅใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
  2. ใ‚ญใƒฅใƒผใฏใƒŽใƒผใƒ‰ใ‚’็•ฐใชใ‚‹้ †ๅบใง่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
  3. ๆคœ็ดขใฏใ‚ฐใƒฉใƒ•ใงใ“ใฎๅ€คใ‚’่ฟฝ่ทกใ—ใ€ใ‚ญใƒฅใƒผใซๆธกใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

1.3.1้‡ใฟไป˜ใใ‚ซใ‚ฆใƒณใƒˆ


ใƒใ‚คใƒณใƒˆfrom_nodeใ‹ใ‚‰้šฃๆŽฅใ™ใ‚‹to_nodeใซ็งปๅ‹•ใ™ใ‚‹ใ‚ณใ‚นใƒˆใ‚’ไผใˆใ‚‹้–ขๆ•ฐcost(from_node, to_node)ใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ ใ“ใฎใƒ•ใ‚ฉใƒฌใ‚นใƒˆใƒžใƒƒใƒ—ใงใฏใ€็งปๅ‹•ใฏto_nodeใฎใฟใซไพๅญ˜ใ™ใ‚‹ใ“ใจใ‚’ๆฑบๅฎšใ—ใพใ—ใŸใŒใ€ ไธกๆ–นใฎใƒŽใƒผใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ไป–ใฎใ‚ฟใ‚คใƒ—ใฎ็งปๅ‹•ใŒใ‚ใ‚Šใพใ™ ใ€‚ ๅฎŸ่ฃ…ใฎไปฃๆ›ฟๆ–นๆณ•ใฏใ€ neighbors้–ขๆ•ฐใซใƒžใƒผใ‚ธใ™ใ‚‹ใ“ใจใงใ™ใ€‚

 class GridWithWeights(SquareGrid): def __init__(self, width, height): super().__init__(width, height) self.weights = {} def cost(self, from_node, to_node): return self.weights.get(to_node, 1) 

1.3.2ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผ


ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฏใ€ๅ„่ฆ็ด ใซใ€Œๅ„ชๅ…ˆๅบฆใ€ใจๅ‘ผใฐใ‚Œใ‚‹็•ชๅทใ‚’้–ข้€ฃไป˜ใ‘ใพใ™ใ€‚ ใ‚ขใ‚คใƒ†ใƒ ใŒ่ฟ”ใ•ใ‚Œใ‚‹ใจใ€ๆœ€ใ‚‚ๅฐใ•ใ„็•ชๅทใฎใ‚ขใ‚คใƒ†ใƒ ใŒ้ธๆŠžใ•ใ‚Œใพใ™ใ€‚

insert ๏ผšใ‚ขใ‚คใƒ†ใƒ ใ‚’ใ‚ญใƒฅใƒผใซ่ฟฝๅŠ ใ—ใพใ™

remove ๏ผšๆœ€ๅฐใฎ็•ชๅทใ‚’ๆŒใค่ฆ็ด ใ‚’ๅ‰Š้™คใ—ใพใ™

reprioritize ๏ผš๏ผˆใ‚ชใƒ—ใ‚ทใƒงใƒณ๏ผ‰ๆ—ขๅญ˜ใฎใ‚ขใ‚คใƒ†ใƒ ใฎๅ„ชๅ…ˆๅบฆใ‚’ไฝŽใ„ๆ•ฐๅ€คใซๅค‰ๆ›ดใ—ใพใ™ใ€‚

ใ“ใ‚Œใฏใ€ ใƒใ‚คใƒŠใƒชใƒ’ใƒผใƒ—ใ‚’ไฝฟ็”จใ—ใพใ™ใŒใ€reprioritizeใงใฏใ‚ตใƒใƒผใƒˆใ•ใ‚Œใชใ„ใ€ใ‹ใชใ‚Š้ซ˜้€Ÿใชๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใงใ™ใ€‚ ๆญฃใ—ใ„้ †ๅบใ‚’ๅ–ๅพ—ใ™ใ‚‹ใซใฏใ€ใ‚ฟใƒ—ใƒซ๏ผˆๅ„ชๅ…ˆ้ †ไฝใ€่ฆ็ด ๏ผ‰ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ ใ™ใงใซใ‚ญใƒฅใƒผใซใ‚ใ‚‹ใ‚ขใ‚คใƒ†ใƒ ใ‚’ๆŒฟๅ…ฅใ™ใ‚‹ใจใ€้‡่ค‡ใ—ใพใ™ใ€‚ ๆœ€้ฉๅŒ–ใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใ“ใ‚ŒใŒ็งใŸใกใซ้ฉใ—ใฆใ„ใ‚‹็†็”ฑใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚

 import heapq class PriorityQueue: def __init__(self): self.elements = [] def empty(self): return len(self.elements) == 0 def put(self, item, priority): heapq.heappush(self.elements, (priority, item)) def get(self): return heapq.heappop(self.elements)[1] 

1.3.3ๆคœ็ดข


ใ“ใ“ใซใฏๅฎŸ่ฃ…ใฎใƒˆใƒชใƒƒใ‚ญใƒผใช็žฌ้–“ใŒใ‚ใ‚Šใพใ™ใ€‚็งปๅ‹•ใฎใ‚ณใ‚นใƒˆใ€ใคใพใ‚Šใ€ใ‚ˆใ‚Š่‰ฏใ„cost_so_farใ‚’ๆŒใคใƒใ‚คใƒณใƒˆใธใฎ็นฐใ‚Š่ฟ”ใ—่จชๅ•ใฎ็ขบ็Ž‡ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ‹ใ‚‰cost_so_far ใ€‚ ใ“ใ‚Œใฏif next not in came_fromใซใชใ„if next not in came_fromใŒๆฉŸ่ƒฝใ—ใชใ„ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ ไปฃใ‚ใ‚Šใซใ€ๆœ€ๅพŒใฎ่จชๅ•ไปฅ้™ใซใ‚ณใ‚นใƒˆใŒๆธ›ๅฐ‘ใ—ใŸใ‹ใฉใ†ใ‹ใ‚’็ขบ่ชใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ ๏ผˆ่จ˜ไบ‹ใฎๅ…ƒใฎใƒใƒผใ‚ธใƒงใƒณใงใฏใ“ใ‚Œใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ›ใ‚“ใงใ—ใŸใŒใ€ใ‚ณใƒผใƒ‰ใฏใจใซใ‹ใๆฉŸ่ƒฝใ—ใพใ—ใŸใ€‚ ใ“ใฎใ‚จใƒฉใƒผใซ้–ขใ™ใ‚‹ใƒกใƒขใ‚’ๆ›ธใใพใ—ใŸ ใ€‚๏ผ‰

ใ“ใฎๆฃฎๆž—ๅœฐๅ›ณใฏๅ‰ใฎ่จ˜ไบ‹ใ‹ใ‚‰ๅ–ใ‚‰ใ‚Œใพใ—ใŸใ€‚

 def dijkstra_search(graph, start, goal): frontier = PriorityQueue() frontier.put(start, 0) came_from = {} cost_so_far = {} came_from[start] = None cost_so_far[start] = 0 while not frontier.empty(): current = frontier.get() if current == goal: break for next in graph.neighbors(current): new_cost = cost_so_far[current] + graph.cost(current, next) if next not in cost_so_far or new_cost < cost_so_far[next]: cost_so_far[next] = new_cost priority = new_cost frontier.put(next, priority) came_from[next] = current return came_from, cost_so_far 

ๆคœ็ดขๅพŒใ€ใƒ‘ใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

 def reconstruct_path(came_from, start, goal): current = goal path = [current] while current != start: current = came_from[current] path.append(current) path.append(start) #  path.reverse() #  return path 

ใƒ‘ใ‚นใฏใ‚จใƒƒใ‚ธใฎใ‚ทใƒผใ‚ฑใƒณใ‚นใจใ—ใฆๆœ€ใ‚‚ใ‚ˆใ็†่งฃใ•ใ‚Œใพใ™ใŒใ€ใƒŽใƒผใƒ‰ใฎใ‚ทใƒผใ‚ฑใƒณใ‚นใจใ—ใฆไฟๅญ˜ใ™ใ‚‹ๆ–นใŒไพฟๅˆฉใงใ™ใ€‚ ใƒ‘ใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใซใฏใ€ๆœ€ๅพŒใ‹ใ‚‰ๅง‹ใ‚ใฆใ€ๅ‰ใฎใƒŽใƒผใƒ‰ใ‚’ๆŒ‡ใ™came_fromใƒžใƒƒใƒ—ใซๅพ“ใ„ใพใ™ใ€‚ ๆœ€ๅˆใซๅˆฐ้”ใ™ใ‚‹ใจใ€ไป•ไบ‹ใฏๅฎŒไบ†ใงใ™ใ€‚ ใ“ใ‚ŒใŒๆˆปใ‚Šใƒ‘ใ‚นใงใ™ใ€‚ใ—ใŸใŒใฃใฆใ€ reconstruct_pathใฎๆœ€ๅพŒใงใ€็›ดๆŽฅใ‚ทใƒผใ‚ฑใƒณใ‚นใงๆ ผ็ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ reverse()ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ ๅฎŸ้š›ใ€ใƒ‘ใ‚นใ‚’้€†ใซไฟๅญ˜ใ™ใ‚‹ๆ–นใŒไพฟๅˆฉใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ ใ•ใ‚‰ใซใ€้–‹ๅง‹ใƒŽใƒผใƒ‰ใ‚’ใƒชใ‚นใƒˆใซไฟๅญ˜ใ™ใ‚‹ใจไพฟๅˆฉใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚

่ฉฆใ—ใฆใฟใพใ—ใ‚‡ใ†๏ผš

 from implementation import * came_from, cost_so_far = dijkstra_search(diagram4, (1, 4), (7, 8)) draw_grid(diagram4, width=3, point_to=came_from, start=(1, 4), goal=(7, 8)) print() draw_grid(diagram4, width=3, number=cost_so_far, start=(1, 4), goal=(7, 8)) print() draw_grid(diagram4, width=3, path=reconstruct_path(came_from, start=(1, 4), goal=(7, 8))) 

โ†“ โ†“ โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ† โ† โ† โ†‘ โ†‘ โ† โ† โ†
โ†“ โ†“ โ† โ† โ† โ† โ†‘ โ†‘ โ† โ†
โ†“ โ†“ โ† โ† โ† โ† โ† โ†‘ โ†‘ .
โ†’ A โ† โ† โ† โ† . . . .
โ†‘ โ†‘ โ† โ† โ† โ† . . . .
โ†‘ โ†‘ โ† โ† โ† โ† โ† . . .
โ†‘ #########โ†‘ โ† โ†“ . . .
โ†‘ #########โ†“ โ†“ โ†“ Z . .
โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† .

5 4 5 6 7 8 9 10 11 12
4 3 4 5 10 13 10 11 12 13
3 2 3 4 9 14 15 12 13 14
2 1 2 3 8 13 18 17 14 .
1 A 1 6 11 16 . . . .
2 1 2 7 12 17 . . . .
3 2 3 4 9 14 19 . . .
4 #########14 19 18 . . .
5 #########15 16 13 Z . .
6 7 8 9 10 11 12 13 14 .

. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
@ @ . . . . . . . .
@ . . . . . . . . .
@ . . . . . . . . .
@ #########. . . . . .
@ #########. . @ @ . .
@ @ @ @ @ @ @ . . .


if next not in cost_so_far or new_cost < cost_so_far[next]ใฎ่กŒif next not in cost_so_far or new_cost < cost_so_far[next] if new_cost < cost_so_far.get(next, Infinity)ใซ็ฐก็•ฅๅŒ–ใงใใพใ™ใŒใ€ๅ‰ๅ›žใฎ่จ˜ไบ‹ใงget() Pythonใ‚’่ชฌๆ˜Žใ—ใŸใใชใ‹ใฃใŸใฎใงใ€ใใฎใพใพใซใ—ใพใ—ใŸใ€‚ ใพใŸใ€ collections.defaultdictใ‚’ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ็„ก้™ๅ€คใงไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚

1.4ๆคœ็ดขA *


ๆœ€้ฉใชๆœ€ๅˆใฎไธ€่‡ดใฎ่ฒชๆฌฒใชๆคœ็ดขใจA *ใฎไธกๆ–นใงใ€ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏ้–ขๆ•ฐใŒไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ ๅ”ฏไธ€ใฎ้•ใ„ใฏใ€A *ใŒใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใจใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎ้ †ๅบใฎไธกๆ–นใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ™ใ€‚ ใ“ใ“ใงA *ใ‚’่กจ็คบใ—ใพใ™ใ€‚

 def heuristic(a, b): (x1, y1) = a (x2, y2) = b return abs(x1 - x2) + abs(y1 - y2) def a_star_search(graph, start, goal): frontier = PriorityQueue() frontier.put(start, 0) came_from = {} cost_so_far = {} came_from[start] = None cost_so_far[start] = 0 while not frontier.empty(): current = frontier.get() if current == goal: break for next in graph.neighbors(current): new_cost = cost_so_far[current] + graph.cost(current, next) if next not in cost_so_far or new_cost < cost_so_far[next]: cost_so_far[next] = new_cost priority = new_cost + heuristic(goal, next) frontier.put(next, priority) came_from[next] = current return came_from, cost_so_far 

่ฉฆใ—ใฆใฟใพใ—ใ‚‡ใ†๏ผš

 from implementation import * came_from, cost_so_far = a_star_search(diagram4, (1, 4), (7, 8)) draw_grid(diagram4, width=3, point_to=came_from, start=(1, 4), goal=(7, 8)) print() draw_grid(diagram4, width=3, number=cost_so_far, start=(1, 4), goal=(7, 8)) 

. . . . . . . . . .
. โ†“ โ†“ โ†“ . . . . . .
โ†“ โ†“ โ†“ โ†“ โ† . . . . .
โ†“ โ†“ โ†“ โ† โ† . . . . .
โ†’ A โ† โ† โ† . . . . .
โ†’ โ†‘ โ† โ† โ† . . . . .
โ†’ โ†‘ โ† โ† โ† โ† . . . .
โ†‘ #########โ†‘ . โ†“ . . .
โ†‘ #########โ†“ โ†“ โ†“ Z . .
โ†‘ โ† โ† โ† โ† โ† โ† โ† . .

. . . . . . . . . .
. 3 4 5 . . . . . .
3 2 3 4 9 . . . . .
2 1 2 3 8 . . . . .
1 A 1 6 11 . . . . .
2 1 2 7 12 . . . . .
3 2 3 4 9 14 . . . .
4 #########14 . 18 . . .
5 #########15 16 13 Z . .
6 7 8 9 10 11 12 13 . .


1.4.1็›ด็ทšใƒ‘ใ‚น


็‹ฌ่‡ชใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซใ“ใฎใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹ใจใ€ไธ€้ƒจใฎใƒ‘ใ‚นใŒๅธŒๆœ›ใฉใŠใ‚Šใฎใ€Œ็›ดๆŽฅใ€ใงใฏใชใ„ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚ ใ“ใ‚Œใฏๆญฃๅธธใงใ™ใ€‚ ใ‚ฐใƒชใƒƒใƒ‰ ใ€็‰นใซๅ„ใ‚นใƒ†ใƒƒใƒ—ใฎ็งปๅ‹•ใ‚ณใ‚นใƒˆใŒๅŒใ˜ใ‚ฐใƒชใƒƒใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€ ๅŒ็ญ‰ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใŒๅพ—ใ‚‰ใ‚Œใพใ™ ใ€‚ๅคšใใฎใƒ‘ใ‚นใฎใ‚ณใ‚นใƒˆใฏใพใฃใŸใๅŒใ˜ใงใ™ใ€‚ *ใฏๅคšใใฎใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆใฎ1ใคใ‚’้ธๆŠžใ—ใพใ™ใŒใ€้žๅธธใซใใ‚Œใ„ใซ่ฆ‹ใˆใชใ„ใ“ใจใŒ้žๅธธใซๅคšใใ‚ใ‚Šใพใ™ ใ€‚ ๅŒ็ญ‰ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ๆŽ’้™คใ™ใ‚‹ใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒƒใ‚ฏใ‚’้ฉ็”จใงใใพใ™ใŒใ€ๅธธใซๅฎŒๅ…จใซ้ฉๅˆ‡ใงใ‚ใ‚‹ใจใฏ้™ใ‚Šใพใ›ใ‚“ใ€‚ ใƒžใƒƒใƒ—ใฎ่กจ็พใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใจใ€ A *ใŒๅคงๅน…ใซๅŠ ้€Ÿใ•ใ‚Œใ€ใ‚ˆใ‚Š็›ดๆŽฅ็š„ใงๅฟซ้ฉใชใƒ‘ใ‚นใŒไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ ใŸใ ใ—ใ€ใ“ใ‚Œใฏใ€ๅ„ใ‚นใƒ†ใƒƒใƒ—ใซ1ใคใฎ็งปๅ‹•ใ‚ณใ‚นใƒˆใŒใ‚ใ‚‹้™็š„ใ‚ซใƒผใƒ‰ใซ้ฉใ—ใฆใ„ใพใ™ใ€‚ ็งใฎใƒšใƒผใ‚ธใฎใƒ‡ใƒขใงใฏใ€็ฐกๅ˜ใชใƒใƒƒใ‚ฏใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใŒใ€ๅ„ชๅ…ˆๅบฆใฎไฝŽใ„ใ‚ญใƒฅใƒผใงใฎใฟๆฉŸ่ƒฝใ—ใพใ™ใ€‚ ใ‚ˆใ‚Š้ซ˜้€Ÿใชๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใซๅˆ‡ใ‚Šๆ›ฟใˆใ‚‹ๅ ดๅˆใฏใ€ๅˆฅใฎใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒƒใ‚ฏใŒๅฟ…่ฆใงใ™ใ€‚

2 C ++ๅฎŸ่ฃ…


ๆณจ๏ผšใ‚ตใƒณใƒ—ใƒซใ‚ณใƒผใƒ‰ใฎไธ€้ƒจใ‚’ๅฎŸ่กŒใ™ใ‚‹ใซใฏใ€ redblobgames / pathfinding / a-star / implementation.cppใ‚’่ฟฝๅŠ ใ—ใพใ™ ใ€‚ ใ“ใฎใ‚ณใƒผใƒ‰ใซใฏC ++ 11ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ๅคใ„ใƒใƒผใ‚ธใƒงใƒณใฎC ++ๆจ™ๆบ–ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€้ƒจๅˆ†็š„ใซๅค‰ๆ›ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

2.1ใƒฏใ‚คใƒ‰ๆคœ็ดข


ๆœ€ๅˆใซPythonใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใซใฏใ‚ณใƒผใƒ‰ใŒใ‚ใ‚Šใพใ™ใŒใ€ๅŒใ˜่ชฌๆ˜Žใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ใพใšใ€ไธ€่ˆฌ็š„ใชใ‚ฐใƒฉใƒ•ใ‚ฏใƒฉใ‚นใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚

 template<typename L> struct SimpleGraph { typedef L Location; typedef typename vector<Location>::iterator iterator; unordered_map<Location, vector<Location> > edges; inline const vector<Location> neighbors(Location id) { return edges[id]; } }; 

charใ‚’ไฝฟ็”จใ—ใฆใƒใ‚คใƒณใƒˆใ‚’ใƒžใƒผใ‚ฏใ™ใ‚‹Pythonใ‚ณใƒผใƒ‰ใฎๅŒใ˜ใ‚ฐใƒฉใƒ•ใฎไพ‹๏ผš

็”ปๅƒ

 SimpleGraph<char> example_graph {{ {'A', {'B'}}, {'B', {'A', 'C', 'D'}}, {'C', {'A'}}, {'D', {'E', 'A'}}, {'E', {'B'}} }}; 

ใ‚ญใƒฅใƒผใ‚ฏใƒฉใ‚นใ‚’ๅฎš็พฉใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€C ++ๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ ใ“ใ‚Œใงใ€ๅน…ๅ„ชๅ…ˆใฎๆคœ็ดขใ‚’่ฉฆใฟใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚

 #include "redblobgames/pathfinding/a-star/implementation.cpp" template<typename Graph> void breadth_first_search(Graph graph, typename Graph::Location start) { typedef typename Graph::Location Location; queue<Location> frontier; frontier.push(start); unordered_set<Location> visited; visited.insert(start); while (!frontier.empty()) { auto current = frontier.front(); frontier.pop(); std::cout << "Visiting " << current << std::endl; for (auto& next : graph.neighbors(current)) { if (!visited.count(next)) { frontier.push(next); visited.insert(next); } } } } int main() { breadth_first_search(example_graph, 'A'); } 

Visiting A
Visiting B
Visiting C
Visiting D
Visiting E


ใ‚ณใƒผใƒ‰ใฏPythonใ‚ˆใ‚Šใ‚‚ๅฐ‘ใ—้•ทใใชใ‚Šใพใ™ใŒใ€ใ“ใ‚Œใฏ้žๅธธใซๆญฃๅธธใงใ™ใ€‚

ๆญฃๆ–นๅฝขใ‚ฐใƒชใƒƒใƒ‰ใฏใฉใ†ใงใ™ใ‹๏ผŸ ๅˆฅใฎใ‚ฏใƒฉใ‚นใฎใ‚ฐใƒฉใƒ•ใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ ใ‚ฐใƒฉใƒ•ใฎๅ‰ใฎใ‚ฏใƒฉใ‚นใจใฏ้–ขไฟ‚ใŒใชใ„ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ ็ถ™ๆ‰ฟใงใฏใชใใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ ใ‚ฐใƒฉใƒ•ใฏใ€typedef Locationใจneighbors้–ขๆ•ฐใฎใฟใ‚’ๆไพ›ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

 struct SquareGrid { typedef tuple<int,int> Location; static array<Location, 4> DIRS; int width, height; unordered_set<Location> walls; SquareGrid(int width_, int height_) : width(width_), height(height_) {} inline bool in_bounds(Location id) const { int x, y; tie (x, y) = id; return 0 <= x && x < width && 0 <= y && y < height; } inline bool passable(Location id) const { return !walls.count(id); } vector<Location> neighbors(Location id) const { int x, y, dx, dy; tie (x, y) = id; vector<Location> results; for (auto dir : DIRS) { tie (dx, dy) = dir; Location next(x + dx, y + dy); if (in_bounds(next) && passable(next)) { results.push_back(next); } } if ((x + y) % 2 == 0) { //      std::reverse(results.begin(), results.end()); } return results; } }; array<SquareGrid::Location, 4> SquareGrid::DIRS {Location{1, 0}, Location{0, -1}, Location{-1, 0}, Location{0, 1}}; 

ใƒ˜ใƒซใƒ‘ใƒผใƒ•ใ‚กใ‚คใƒซimplementation.cppใ‚ฐใƒชใƒƒใƒ‰ใ‚’ใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใ™ใ‚‹ใŸใ‚ใฎ้–ขๆ•ฐใ‚’ๅฎš็พฉใ—ใพใ—ใŸใ€‚

 #include "redblobgames/pathfinding/a-star/implementation.cpp" int main() { SquareGrid grid = make_diagram1(); draw_grid(grid, 2); } 

. . . . . . . . . . . . . . . . . . . . . ####. . . . . . .
. . . . . . . . . . . . . . . . . . . . . ####. . . . . . .
. . . . . . . . . . . . . . . . . . . . . ####. . . . . . .
. . . ####. . . . . . . . . . . . . . . . ####. . . . . . .
. . . ####. . . . . . . . ####. . . . . . ####. . . . . . .
. . . ####. . . . . . . . ####. . . . . . ##########. . . .
. . . ####. . . . . . . . ####. . . . . . ##########. . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . ####. . . . . . . . ####. . . . . . . . . . . . . . .
. . . . . . . . . . . . . ####. . . . . . . . . . . . . . .
. . . . . . . . . . . . . ####. . . . . . . . . . . . . . .
. . . . . . . . . . . . . ####. . . . . . . . . . . . . . .


came_from่ฟฝ่ทกใ—ใฆใ€ๅน…ๅ„ชๅ…ˆใฎๆคœ็ดขใ‚’่กŒใ„ใพใ—ใ‚‡ใ†ใ€‚

 #include "redblobgames/pathfinding/a-star/implementation.cpp" template<typename Graph> unordered_map<typename Graph::Location, typename Graph::Location> breadth_first_search(Graph graph, typename Graph::Location start) { typedef typename Graph::Location Location; queue<Location> frontier; frontier.push(start); unordered_map<Location, Location> came_from; came_from[start] = start; while (!frontier.empty()) { auto current = frontier.front(); frontier.pop(); for (auto& next : graph.neighbors(current)) { if (!came_from.count(next)) { frontier.push(next); came_from[next] = current; } } } return came_from; } int main() { SquareGrid grid = make_diagram1(); auto parents = breadth_first_search(grid, std::make_tuple(7, 8)); draw_grid(grid, 2, nullptr, &parents); } 

โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† โ† ####โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†’ โ†‘ ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† โ† โ† ####โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“
โ†’ โ†‘ โ†‘ ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† ####โ†‘ โ† โ† โ† โ† โ† ####โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“
โ†‘ โ†‘ โ†‘ ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† ####โ†‘ โ†‘ โ† โ† โ† โ† ##########โ†“ โ†“ โ†“ โ†
โ†‘ โ†‘ โ†‘ ####โ†’ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ† โ† โ† ##########โ†“ โ†“ โ† โ†
โ†“ โ†“ โ†“ ####โ†’ โ†’ โ†“ โ†“ โ† โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ ####โ†’ โ†’ * โ† โ† โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ ####โ†’ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ† โ†
โ†’ โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ† โ†
โ†’ โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ† โ†
โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ† โ†
โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† โ† โ†


ๅฎŸ่ฃ…ใซใ‚ˆใฃใฆใฏใ€ ๅ†…้ƒจใ‚นใƒˆใƒฌใƒผใ‚ธใ‚’ไฝฟ็”จใ—ใฆNodeใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใ€ came_fromใŠใ‚ˆใณใ‚ฐใƒฉใƒ•ๅ†…ใฎๅ„ใƒŽใƒผใƒ‰ใฎใใฎไป–ใฎๅ€คใ‚’ไฟๅญ˜ใ—ใพใ™ใ€‚ ๅค–้ƒจใ‚นใƒˆใƒฌใƒผใ‚ธใ‚’ไฝฟ็”จใ—ใฆใ€ๅ˜ไธ€ใฎstd::unordered_mapใ‚’ไฝœๆˆใ—ใฆใ€ใ‚ฐใƒฉใƒ•ใฎใ™ในใฆใฎใƒŽใƒผใƒ‰ใฎcame_fromใ‚’ไฟๅญ˜ใ™ใ‚‹ใ“ใจใ‚’came_fromใพใ—ใŸใ€‚ ใƒžใƒƒใƒ—ไธŠใฎใƒใ‚คใƒณใƒˆใซๆ•ดๆ•ฐใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๅˆฅใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ™ใ€‚1ๆฌกๅ…ƒใพใŸใฏ2ๆฌกๅ…ƒใฎ้…ๅˆ—/ใƒ™ใ‚ฏใƒˆใƒซใ‚’ไฝฟ็”จใ—ใฆcame_fromใŠใ‚ˆใณใใฎไป–ใฎๅ€คใ‚’ๆ ผ็ดใ—ใพใ™ใ€‚

2.1.1 TODO๏ผšๆง‹้€ ไฝ“ใƒใ‚คใƒณใƒˆ


ใ“ใฎใ‚ณใƒผใƒ‰ใงใฏใ€Pythonใ‚ณใƒผใƒ‰ใงใ‚ฟใƒ—ใƒซใ‚’ไฝฟ็”จใ—ใŸใŸใ‚ใ€ std::tuple C ++ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ ใŸใ ใ—ใ€ใ‚ฟใƒ—ใƒซใฏใปใจใ‚“ใฉใฎC ++ใƒ—ใƒญใ‚ฐใƒฉใƒžใซใฏ้ฆดๆŸ“ใฟใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ใ‚ณใƒณใ‚นใƒˆใƒฉใ‚ฏใ‚ฟใƒผใ€ใ‚ณใƒ”ใƒผใ‚ณใƒณใ‚นใƒˆใƒฉใ‚ฏใ‚ฟใƒผใ€ไปฃๅ…ฅๆผ”็ฎ—ๅญใ€ใŠใ‚ˆใณใƒใƒƒใ‚ทใƒฅ้–ขๆ•ฐใจใฎ็ญ‰ไพกๆฏ”่ผƒใ‚’ๅฎš็พฉใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใ€{xใ€y}ใ‚’ไฝฟ็”จใ—ใฆๆง‹้€ ไฝ“ใ‚’ๅฎš็พฉใ™ใ‚‹ใฎใฏใ‚‚ใ†ๅฐ‘ใ—้•ทใใชใ‚Šใพใ™ใŒใ€ใ“ใฎใ‚ณใƒผใƒ‰ใฏใปใจใ‚“ใฉใฎC ++ใƒ—ใƒญใ‚ฐใƒฉใƒžใƒผใซใ‚ˆใ็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ ๅค‰ๆ›ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

ใ‚‚ใ†1ใคใฎใ‚ชใƒ—ใ‚ทใƒงใƒณ๏ผˆใ‚ณใƒผใƒ‰ใงไฝฟ็”จ๏ผ‰ใฏใ€{xใ€y}ใ‚’intใจใ—ใฆใ‚จใƒณใ‚ณใƒผใƒ‰ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ T A *ใ‚ณใƒผใƒ‰ใซใ€ไปปๆ„ใฎLocationใ‚ฟใ‚คใƒ—ใงใฏใชใใ€ๅธธใซๆ•ดๆ•ฐๅ€คใฎๅฏ†ใชใ‚ปใƒƒใƒˆใŒใ‚ใ‚‹ๅ ดๅˆใ€ใ“ใ‚Œใซใ‚ˆใ‚Š่ฟฝๅŠ ใฎๆœ€้ฉๅŒ–ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ ใƒใƒƒใ‚ทใƒฅใƒ†ใƒผใƒ–ใƒซใงใฏใชใใ€็•ฐใชใ‚‹ใ‚ปใƒƒใƒˆใซ้…ๅˆ—ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ ใใ‚Œใ‚‰ใฎใปใจใ‚“ใฉใ‚’ๅˆๆœŸๅŒ–ใ›ใšใซๆฎ‹ใ™ใ“ใจใŒใงใใพใ™ใ€‚ ๆฏŽๅ›žๅ†ๅˆๆœŸๅŒ–ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹้…ๅˆ—ใฎๅ ดๅˆใ€A *ๅ‘ผใณๅ‡บใ—ใงๅฎšๆ•ฐใซใ—๏ผˆใŠใใ‚‰ใใƒญใƒผใ‚ซใƒซใ‚นใƒฌใƒƒใƒ‰ใ‚นใƒˆใ‚ขใ‚’ไฝฟ็”จ๏ผ‰ใ€ๅ‰ใฎๅ‘ผใณๅ‡บใ—ใงไฝฟ็”จใ•ใ‚ŒใŸ้…ๅˆ—ใฎ้ƒจๅˆ†ใฎใฟใ‚’ๅ†ๅˆๆœŸๅŒ–ใงใใพใ™ใ€‚ ใ“ใ‚Œใฏใ€ใ‚จใƒณใƒˆใƒชใƒผใƒฌใƒ™ใƒซใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏไฝฟ็”จใ—ใŸใใชใ„ใ€ใ‚ˆใ‚Š่ค‡้›‘ใชๆ‰‹ๆณ•ใงใ™ใ€‚

2.2ๆ—ฉๆœŸ้€€ๅ‡บ


Pythonใฎใƒใƒผใ‚ธใƒงใƒณใจๅŒๆง˜ใซใ€้–ขๆ•ฐใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’่ฟฝๅŠ ใ—ใฆใƒกใ‚คใƒณใƒซใƒผใƒ—ใ‚’็ขบ่ชใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚

 #include "redblobgames/pathfinding/a-star/implementation.cpp" template<typename Graph> unordered_map<typename Graph::Location, typename Graph::Location> breadth_first_search(const Graph& graph, typename Graph::Location start, typename Graph::Location goal) { typedef typename Graph::Location Location; queue<Location> frontier; frontier.push(start); unordered_map<Location, Location> came_from; came_from[start] = start; while (!frontier.empty()) { auto current = frontier.front(); frontier.pop(); if (current == goal) { break; } for (auto& next : graph.neighbors(current)) { if (!came_from.count(next)) { frontier.push(next); came_from[next] = current; } } } return came_from; } int main() { SquareGrid grid = make_diagram1(); auto parents = breadth_first_search(grid, SquareGrid::Location{8, 7}, SquareGrid::Location{17, 2}); draw_grid(grid, 2, nullptr, &parents); } 

. โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† . . . . ####. . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† . . . ####. . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† . . . ####. . . . . . .
โ†’ โ†’ โ†‘ ####โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ† . . ####. . . . . . .
. โ†‘ โ†‘ ####โ†’ โ†“ โ†“ โ†“ โ†“ โ†“ โ†“ โ† ####โ†‘ โ† โ† . . . ####. . . . . . .
. . โ†‘ ####โ†’ โ†’ โ†“ โ†“ โ†“ โ†“ โ† โ† ####โ†‘ โ†‘ . . . . ##########. . . .
. . . ####โ†’ โ†’ โ†’ โ†“ โ†“ โ† โ† โ† ####โ†‘ . . . . . ##########. . . .
. . . ####โ†’ โ†’ โ†’ * โ† โ† โ† โ† ####. . . . . . . . . . . . . . .
. . . ####โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ† โ† โ† ####. . . . . . . . . . . . . . .
. . โ†“ ####โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† โ† ####. . . . . . . . . . . . . . .
. โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ† ####. . . . . . . . . . . . . . .
โ†’ โ†“ โ†“ ####โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .
โ†’ โ†’ โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .
. โ†’ โ†’ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ โ†‘ ####. . . . . . . . . . . . . . .


2.3ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ 


2.3.1้‡ใฟไป˜ใใ‚ซใ‚ฆใƒณใƒˆ


็งปๅ‹•ใฎใ‚ณใ‚นใƒˆใŒ5ใงใ‚ใ‚‹ใƒ•ใ‚ฉใƒฌใ‚นใƒˆใ‚ฟใ‚คใƒซใฎใƒชใ‚นใƒˆใ‚’ๆŒใคใ‚ฐใƒชใƒƒใƒ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใฎใƒ•ใ‚ฉใƒฌใ‚นใƒˆใƒžใƒƒใƒ—ใงใฏใ€ to_nodeใฎใฟใซto_node็งปๅ‹•ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ“ใจใซใ—to_node ใ€ ไธกๆ–นใฎใƒŽใƒผใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ไป–ใฎใ‚ฟใ‚คใƒ—ใฎ็งปๅ‹•ใŒใ‚ใ‚Šใพใ™ ใ€‚

 struct GridWithWeights: SquareGrid { unordered_set<Location> forests; GridWithWeights(int w, int h): SquareGrid(w, h) {} double cost(Location from_node, Location to_node) const { return forests.count(to_node) ? 5 : 1; } }; 

2.3.2ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผ


ๅ„ชๅ…ˆใ‚ญใƒฅใƒผใŒๅฟ…่ฆใงใ™ใ€‚ C ++ใซใฏใ€ใƒใ‚คใƒŠใƒชใƒ’ใƒผใƒ—ใ‚’ไฝฟ็”จใ™ใ‚‹priority_queueใ‚ฏใƒฉใ‚นใŒใ‚ใ‚Šใพใ™ใŒใ€ๅ„ชๅ…ˆๅบฆใฎๅค‰ๆ›ดๆ“ไฝœใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ใ‚ญใƒฅใƒผ่ฆ็ด ใซๆญฃใ—ใ„้ †ๅบใ‚’ๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซใƒšใ‚ข๏ผˆๅ„ชๅ…ˆๅบฆใ€่ฆ็ด ๏ผ‰ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€C ++ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฏๆœ€ๅˆใซstd::lessใ‚ณใƒณใƒ‘ใƒฌใƒผใ‚ฟใƒผใ‚’ไฝฟ็”จใ—ใฆๆœ€ๅคง่ฆ็ด ใ‚’่ฟ”ใ—ใพใ™ใ€‚ ๆœ€ๅฐ้™ใฎ่ฆ็ด ใŒๅฟ…่ฆใชใฎใงใ€ std::greaterใ‚ณใƒณใƒ‘ใƒฌใƒผใ‚ฟใƒผใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚

 template<typename T, typename priority_t> struct PriorityQueue { typedef pair<priority_t, T> PQElement; priority_queue<PQElement, vector<PQElement>, std::greater<PQElement>> elements; inline bool empty() const { return elements.empty(); } inline void put(T item, priority_t priority) { elements.emplace(priority, item); } inline T get() { T best_item = elements.top().second; elements.pop(); return best_item; } }; 

ใ“ใฎใ‚ตใƒณใƒ—ใƒซใ‚ณใƒผใƒ‰ใงใฏใ€C ++ std::priority_queueใ‚’ใƒฉใƒƒใƒ—ใ—ใฆใ„ใพใ™ใŒใ€ใ“ใฎใ‚ฏใƒฉใ‚นใ‚’ใƒฉใƒƒใƒ‘ใƒผใชใ—ใงไฝฟ็”จใ™ใ‚‹ใฎใŒ่ณขๆ˜Žใ ใจๆ€ใ„ใพใ™ใ€‚

2.3.3ๆคœ็ดข


ๅ‰ใฎ่จ˜ไบ‹ใฎๆฃฎใฎๅœฐๅ›ณใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚

 template<typename Graph> void dijkstra_search (const Graph& graph, typename Graph::Location start, typename Graph::Location goal, unordered_map<typename Graph::Location, typename Graph::Location>& came_from, unordered_map<typename Graph::Location, double>& cost_so_far) { typedef typename Graph::Location Location; PriorityQueue<Location, double> frontier; frontier.put(start, 0); came_from[start] = start; cost_so_far[start] = 0; while (!frontier.empty()) { auto current = frontier.get(); if (current == goal) { break; } for (auto& next : graph.neighbors(current)) { double new_cost = cost_so_far[current] + graph.cost(current, next); if (!cost_so_far.count(next) || new_cost < cost_so_far[next]) { cost_so_far[next] = new_cost; came_from[next] = current; frontier.put(next, new_cost); } } } } 

costๅค‰ๆ•ฐใฎใ‚ฟใ‚คใƒ—ใฏใ€ใ‚ฐใƒฉใƒ•ใงไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ฟใ‚คใƒ—ใจไธ€่‡ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ intใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฎๅฏๅค‰ใ‚ณใ‚นใƒˆใจๅ„ชๅ…ˆๅบฆใซintใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ doubleใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฏใ€ใใ‚Œใ‚‰ใซใ‚‚doubleใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ ใ“ใฎใ‚ณใƒผใƒ‰ใงใฏdoubleใ‚’ไฝฟ็”จใ—ใพใ—ใŸใŒใ€ intใ‚’ไฝฟ็”จใงใใ€ใ‚ณใƒผใƒ‰ใฏๅŒใ˜ใ‚ˆใ†ใซๆฉŸ่ƒฝใ—ใพใ™ใ€‚ ใŸใ ใ—ใ€ใ‚ฐใƒฉใƒ•ใฎใ‚จใƒƒใ‚ธใฎใ‚ณใ‚นใƒˆใŒdoubleใงๆ ผ็ดใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ใพใŸใฏdoubleใŒใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใงไฝฟ็”จใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ใ“ใ“ใงdoubleใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

ๆœ€ๅพŒใซใ€ๆคœ็ดขๅพŒใ€ใƒ‘ใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

 template<typename Location> vector<Location> reconstruct_path( Location start, Location goal, unordered_map<Location, Location>& came_from ) { vector<Location> path; Location current = goal; path.push_back(current); while (current != start) { current = came_from[current]; path.push_back(current); } path.push_back(start); //  std::reverse(path.begin(), path.end()); return path; } 

ใƒ‘ใ‚นใฏใ‚จใƒƒใ‚ธใฎใ‚ทใƒผใ‚ฑใƒณใ‚นใจใ—ใฆๆœ€ใ‚‚ใ‚ˆใ็†่งฃใ•ใ‚Œใพใ™ใŒใ€ใƒŽใƒผใƒ‰ใฎใ‚ทใƒผใ‚ฑใƒณใ‚นใจใ—ใฆไฟๅญ˜ใ™ใ‚‹ใจไพฟๅˆฉใงใ™ใ€‚ ใƒ‘ใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใซใฏใ€ๆœ€ๅพŒใ‹ใ‚‰ๅง‹ใ‚ใฆcame_fromใƒžใƒƒใƒ—ใซๅพ“ใ„ใ€ๅ‰ใฎใƒŽใƒผใƒ‰ใ‚’came_fromใพใ™ใ€‚ ใƒ—ใƒญใ‚ปใ‚นใฏๆœ€ๅˆใซๅˆฐ้”ใ™ใ‚‹ใจ็ต‚ไบ†ใ—ใพใ™ใ€‚ ใ“ใ‚Œใฏๆˆปใ‚Šใƒ‘ใ‚นใชใฎใงใ€็›ดๆŽฅไฟๅญ˜ใ™ใ‚‹ๅ ดๅˆใฏใ€ reconstruct_pathใฎๆœ€ๅพŒใซreverse()ใ‚’ๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ ใƒ‘ใ‚นใ‚’้€†ใซไฟๅญ˜ใ™ใ‚‹ๆ–นใŒไพฟๅˆฉใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ ใพใŸใ€้–‹ๅง‹ใƒŽใƒผใƒ‰ใ‚’ใƒชใ‚นใƒˆใซไฟๅญ˜ใ™ใ‚‹ใจไพฟๅˆฉใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚

่ฉฆใ—ใฆใฟใพใ—ใ‚‡ใ†๏ผš

 #include "redblobgames/pathfinding/a-star/implementation.cpp" int main() { GridWithWeights grid = make_diagram4(); SquareGrid::Location start{1, 4}; SquareGrid::Location goal{8, 5}; unordered_map<SquareGrid::Location, SquareGrid::Location> came_from; unordered_map<SquareGrid::Location, double> cost_so_far; dijkstra_search(grid, start, goal, came_from, cost_so_far); draw_grid(grid, 2, nullptr, &came_from); std::cout << std::endl; draw_grid(grid, 3, &cost_so_far, nullptr); std::cout << std::endl; vector<SquareGrid::Location> path = reconstruct_path(start, goal, came_from); draw_grid(grid, 3, nullptr, nullptr, &path); } 

โ†“ โ†“ โ† โ† โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ† โ† โ† โ†‘ โ†‘ โ† โ† โ†
โ†“ โ†“ โ† โ† โ† โ† โ†‘ โ†‘ โ† โ†
โ†“ โ†“ โ† โ† โ† โ† โ† โ†‘ โ†‘ โ†
โ†’ * โ† โ† โ† โ† โ† โ†’ โ†‘ โ†
โ†‘ โ†‘ โ† โ† โ† โ† . โ†“ โ†‘ .
โ†‘ โ†‘ โ† โ† โ† โ† โ† โ†“ โ† .
โ†‘ ######โ†‘ โ† โ†“ โ†“ โ† .
โ†‘ ######โ†“ โ†“ โ†“ โ† โ† โ†
โ†‘ โ† โ† โ† โ† โ† โ† โ† โ† โ†

5 4 5 6 7 8 9 10 11 12
4 3 4 5 10 13 10 11 12 13
3 2 3 4 9 14 15 12 13 14
2 1 2 3 8 13 18 17 14 15
1 0 1 6 11 16 21 20 15 16
2 1 2 7 12 17 . 21 16 .
3 2 3 4 9 14 19 16 17 .
4 #########14 19 18 15 16 .
5 #########15 16 13 14 15 16
6 7 8 9 10 11 12 13 14 15

. @ @ @ @ @ @ . . .
. @ . . . . @ @ . .
. @ . . . . . @ @ .
. @ . . . . . . @ .
. @ . . . . . . @ .
. . . . . . . . @ .
. . . . . . . . . .
. #########. . . . . .
. #########. . . . . .
. . . . . . . . . .


ๅ„ชๅ…ˆใ‚ญใƒฅใƒผใงใฏ็ต„ใฟ่พผใฟใฎใƒใƒƒใ‚ทใƒฅใƒ†ใƒผใƒ–ใƒซใ‚’ไฝฟ็”จใ—ใ€ใƒใƒƒใ‚ทใƒฅใƒ†ใƒผใƒ–ใƒซใฎๅๅพฉ้ †ๅบใŒไธ€ๅฎšใงใฏใชใ„ใŸใ‚ใ€็ตๆžœใฏPythonใƒใƒผใ‚ธใƒงใƒณใฎ็ตๆžœใจๅฎŒๅ…จใซใฏไธ€่‡ดใ—ใพใ›ใ‚“ใ€‚

2.4ๆคœ็ดขA *


*ใฏใ€่ฟฝๅŠ ใ•ใ‚ŒใŸใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏๆคœ็ดขใ‚’้™คใใ€ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ใปใผๅฎŒๅ…จใซ็นฐใ‚Š่ฟ”ใ—ใพใ™ใ€‚ ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚ณใƒผใƒ‰ใฏใ‚ฐใƒชใƒƒใƒ‰ใ ใ‘ใงใชใไฝฟ็”จใงใใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ ใ‚ฐใƒชใƒƒใƒ‰ใฎ็Ÿฅ่ญ˜ใฏใ€ใ‚ฐใƒฉใƒ•ใ‚ฏใƒฉใ‚น๏ผˆใ“ใฎๅ ดๅˆใฏSquareGrids ๏ผ‰ใจheuristic้–ขๆ•ฐใซใ‚ใ‚Šใพใ™ใ€‚ ใใ‚Œใ‚‰ใ‚’็ฝฎใๆ›ใˆใ‚‹ๅ ดๅˆใ€ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚ณใƒผใƒ‰A *ใ‚’ไป–ใฎใ‚ฐใƒฉใƒ•ๆง‹้€ ใงไฝฟ็”จใงใใพใ™ใ€‚

 inline double heuristic(SquareGrid::Location a, SquareGrid::Location b) { int x1, y1, x2, y2; tie (x1, y1) = a; tie (x2, y2) = b; return abs(x1 - x2) + abs(y1 - y2); } template<typename Graph> void a_star_search (const Graph& graph, typename Graph::Location start, typename Graph::Location goal, unordered_map<typename Graph::Location, typename Graph::Location>& came_from, unordered_map<typename Graph::Location, double>& cost_so_far) { typedef typename Graph::Location Location; PriorityQueue<Location, double> frontier; frontier.put(start, 0); came_from[start] = start; cost_so_far[start] = 0; while (!frontier.empty()) { auto current = frontier.get(); if (current == goal) { break; } for (auto& next : graph.neighbors(current)) { double new_cost = cost_so_far[current] + graph.cost(current, next); if (!cost_so_far.count(next) || new_cost < cost_so_far[next]) { cost_so_far[next] = new_cost; double priority = new_cost + heuristic(next, goal); frontier.put(next, priority); came_from[next] = current; } } } } 

priorityๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใซไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ฟใ‚คใƒ—ใ‚’ๅซใ‚€ๅ€คใฎใ‚ฟใ‚คใƒ—ใฏใ€ใ‚ฐใƒฉใƒ•ใฎใ‚ณใ‚นใƒˆ๏ผˆcost_t๏ผ‰ใจใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏๅ€คใฎไธกๆ–นใ‚’ๅซใ‚ใ‚‹ใฎใซๅๅˆ†ใชๅคงใใ•ใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใŸใจใˆใฐใ€ใ‚ฐใƒฉใƒ•ใฎๅ€คใŒintใซๆ ผ็ดใ•ใ‚ŒใฆใŠใ‚Šใ€ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใŒdoubleใ‚’่ฟ”ใ™ๅ ดๅˆใ€ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใŒdoubleใ‚’ๅ—ไฟกใงใใ‚‹ใ“ใจใŒๅฟ…่ฆใงใ™ใ€‚ใ“ใฎใ‚ณใƒผใƒ‰ไพ‹ใงใฏใ€double3ใคใฎๅ€ค๏ผˆๅ€คใ€ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใ€ใŠใ‚ˆใณๅ„ชๅ…ˆ้ †ไฝ๏ผ‰ใ™ในใฆใซไฝฟ็”จใ—ใฆใ„ใพใ™ใŒintใ€ๅ€คใจใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใซใฏๆ•ดๆ•ฐๅ€คใŒใ‚ใ‚‹ใŸใ‚ใ€andใ‚’ไฝฟ็”จใงใใพใ™ใ€‚

็ฐกๅ˜ใชใƒกใƒข๏ผšใใ‚Œใฏๆ›ธใ่พผใฟใซ่‰ฏใ„ใ ใ‚ใ†frontier.put(start, heuristic(start, goal))ใ€ใจใงใฏใ‚ใ‚Šใพใ›ใ‚“frontier.put(start, 0)ใ€ใŸใ ใ—ใ€้–‹ๅง‹ใƒŽใƒผใƒ‰ใฎๅ„ชๅ…ˆ้ †ไฝใฏ้‡่ฆใงใฏใชใ„ใŸใ‚ใ€ใ“ใ“ใงใฏ้‡่ฆใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ“ใ‚Œใฏๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฎๅ”ฏไธ€ใฎใƒŽใƒผใƒ‰ใงใ‚ใ‚Šใ€ใใ“ใซไฝ•ใ‹ใŒๆ›ธใ่พผใพใ‚Œใ‚‹ๅ‰ใซ้ธๆŠžใŠใ‚ˆใณๅ‰Š้™คใ•ใ‚Œใพใ™ใ€‚

 #include "redblobgames/pathfinding/a-star/implementation.cpp" int main() { GridWithWeights grid = make_diagram4(); SquareGrid::Location start{1, 4}; SquareGrid::Location goal{8, 5}; unordered_map<SquareGrid::Location, SquareGrid::Location> came_from; unordered_map<SquareGrid::Location, double> cost_so_far; a_star_search(grid, start, goal, came_from, cost_so_far); draw_grid(grid, 2, nullptr, &came_from); std::cout << std::endl; draw_grid(grid, 3, &cost_so_far, nullptr); std::cout << std::endl; vector<SquareGrid::Location> path = reconstruct_path(start, goal, came_from); draw_grid(grid, 3, nullptr, nullptr, &path); } 

โ†“ โ†“ โ†“ โ†“ โ† โ† โ† โ† โ† โ†
โ†“ โ†“ โ†“ โ†“ โ† โ†‘ โ†‘ โ† โ† โ†
โ†“ โ†“ โ†“ โ†“ โ† โ† โ†‘ โ†‘ โ† โ†
โ†“ โ†“ โ†“ โ† โ† โ† . โ†‘ โ†‘ โ†
โ†’ * โ† โ† โ† โ† . โ†’ โ†‘ โ†
โ†’ โ†‘ โ† โ† โ† โ† . . โ†‘ .
โ†‘ โ†‘ โ†‘ โ† โ† โ† . . . .
โ†‘ ######โ†‘ . . . . .
โ†‘ ######. . . . . .
โ†‘ . . . . . . . . .

5 4 5 6 7 8 9 10 11 12
4 3 4 5 10 13 10 11 12 13
3 2 3 4 9 14 15 12 13 14
2 1 2 3 8 13 . 17 14 15
1 0 1 6 11 16 . 20 15 16
2 1 2 7 12 17 . . 16 .
3 2 3 4 9 14 . . . .
4 #########14 . . . . .
5 #########. . . . . .
6 . . . . . . . . .

. . . @ @ @ @ . . .
. . . @ . . @ @ . .
. . . @ . . . @ @ .
. . @ @ . . . . @ .
. @ @ . . . . . @ .
. . . . . . . . @ .
. . . . . . . . . .
. #########. . . . . .
. #########. . . . . .
. . . . . . . . . .


2.4.1็›ด็ทšๅŒ–


ใ“ใฎใ‚ณใƒผใƒ‰ใ‚’ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซๅฎŸ่ฃ…ใ™ใ‚‹ใจใ€ไธ€้ƒจใฎใƒ‘ใ‚นใŒๅธŒๆœ›ใฉใŠใ‚Šใซใ€Œ็›ดๆŽฅใ€ใงใฏใชใ„ใ“ใจใซๆฐ—ไป˜ใใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ“ใ‚Œใฏๅคงไธˆๅคซใงใ™ใ€‚ใ‚ฐใƒชใƒƒใƒ‰ใ€็‰นใซๅ„ใ‚นใƒ†ใƒƒใƒ—ใฎ็งปๅ‹•ใ‚ณใ‚นใƒˆใŒๅŒใ˜ใ‚ฐใƒชใƒƒใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€็ตๆžœใฏๅŒ็ญ‰ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใซใชใ‚Šใพใ™ใ€‚ๅคšใใฎใƒ‘ใ‚นใฎใ‚ณใ‚นใƒˆใฏๅŒใ˜ใงใ™ใ€‚*ใฏๅคšใใฎๆœ€็Ÿญใƒ‘ใ‚นใฎ1ใคใ‚’้ธๆŠžใ—ใพใ™ใŒใ€้žๅธธใซใใ‚Œใ„ใซ่ฆ‹ใˆใชใ„ใ“ใจใŒ้žๅธธใซๅคšใใ‚ใ‚Šใพใ™ใ€‚ๅŒ็ญ‰ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฏ็ฐกๅ˜ใชใƒใƒƒใ‚ฏใงๆŽ’้™คใงใใพใ™ใŒใ€ๅฎŒๅ…จใซ้ฉๅˆ‡ใจใ„ใ†ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใƒžใƒƒใƒ—ใƒ“ใƒฅใƒผใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใ‚’ใŠๅ‹งใ‚ใ—ใพใ™ใ€A *ใ‚’ๅคงๅน…ใซๅŠ ้€Ÿใ—ใ€ใ‚ˆใ‚Š็›ดๆŽฅ็š„ใง็พŽใ—ใ„ใƒ‘ใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใŸใ ใ—ใ€ใ“ใ‚Œใฏๅ„ใ‚นใƒ†ใƒƒใƒ—ใฎ็งปๅ‹•ใ‚ณใ‚นใƒˆใŒๅŒใ˜้™็š„ใ‚ซใƒผใƒ‰ใงใฎใฟๆฉŸ่ƒฝใ—ใพใ™ใ€‚็งใฎใƒšใƒผใ‚ธใฎใƒ‡ใƒขใงใฏใ€ใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒƒใ‚ฏใ‚’ไฝฟ็”จใ—ใพใ—ใŸใŒใ€ๅ„ชๅ…ˆๅบฆใฎไฝŽใ„ใ‚ญใƒฅใƒผใงใฎใฟๆฉŸ่ƒฝใ—ใพใ™ใ€‚ใ‚ˆใ‚Š้ซ˜้€Ÿใชๅ„ชๅ…ˆใ‚ญใƒฅใƒผใซ็งปๅ‹•ใ™ใ‚‹ๅ ดๅˆใฏใ€ๅˆฅใฎ้ซ˜้€Ÿใƒใƒƒใ‚ฏใŒๅฟ…่ฆใงใ™ใ€‚

2.4.2 TODO๏ผšใƒ™ใ‚ฏใƒˆใƒซใƒใ‚คใƒใƒผ๏ผˆ๏ผ‰ใ‚’ๆธกใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™


้šฃไบบใฎๆ–ฐใ—ใ„ใƒ™ใ‚ฏใƒˆใƒซใ‚’ๆฏŽๅ›žๅผท่ชฟ่กจ็คบใ—ใฆ่ฟ”ใ™ไปฃใ‚ใ‚Šใซใ€A *ใ‚ณใƒผใƒ‰ใฏ1ใคใฎใƒ™ใ‚ฏใƒˆใƒซใ‚’้ธๆŠžใ—ใ€ๆฏŽๅ›žใใ‚Œใ‚’้šฃไบบ้–ขๆ•ฐใซๆธกใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚็งใฎใƒ†ใ‚นใƒˆใงใฏใ€ใ“ใ‚Œใซใ‚ˆใ‚Šใ‚ณใƒผใƒ‰ใŒใฏใ‚‹ใ‹ใซ้ซ˜้€Ÿใซใชใ‚Šใพใ—ใŸใ€‚

2.4.3 TODO๏ผšใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผๅŒ–ใ‚’ๆŽ’้™ค


ใ“ใฎใƒšใƒผใ‚ธใฎ็›ฎ็š„ใฏใ€็†่งฃใ—ใ‚„ใ™ใ„ใ‚ณใƒผใƒ‰ใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใงใ™ใ€‚ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚’ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผๅŒ–ใ™ใ‚‹ใจใ€ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎ่ชญใฟๅ–ใ‚ŠใŒ่ค‡้›‘ใซใชใ‚Šใ™ใŽใ‚‹ใจๆ€ใ„ใพใ™ใ€‚ไปฃใ‚ใ‚Šใซใ€ใ„ใใคใ‹ใฎtypedefใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚

2.4.4 TODO๏ผš่ฆไปถใฎ่ฟฝๅŠ 


ใ‚ฐใƒฉใƒ•ใซใฏ2ใคใฎใ‚ฟใ‚คใƒ—๏ผˆ้‡ใฟไป˜ใใŠใ‚ˆใณ้‡ใฟใชใ—๏ผ‰ใŒใ‚ใ‚Šใ€ใ‚ฐใƒฉใƒ•ๆคœ็ดขใ‚ณใƒผใƒ‰ใงใฏใ€ใฉใฎใ‚ฟใ‚คใƒ—ใŒใฉใ“ใงๅฟ…่ฆใ‹ใฏใ‚ใ‹ใ‚Šใพใ›ใ‚“ใ€‚

3 CใงใฎๅฎŸ่ฃ…๏ผƒ


ใ“ใ‚Œใ‚‰ใฏ็งใฎๆœ€ๅˆใฎC๏ผƒใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ‚ใ‚‹ใŸใ‚ใ€ใ“ใฎ่จ€่ชžใงใฏ็‰นๅพด็š„ใงใชใ„ใ‹ใ€ใ‚นใ‚ฟใ‚คใƒซใŒๆญฃใ—ใใชใ„ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎไพ‹ใฏใ€PythonใŠใ‚ˆใณC ++ใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎไพ‹ใปใฉๅฎŒๅ…จใงใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ๅฝนใซ็ซ‹ใคใ“ใจใ‚’้ก˜ใฃใฆใ„ใพใ™ใ€‚ไปฅไธ‹ใซใ€ๅ˜็ด”ใชใ‚ฐใƒฉใƒ•ใจๅน…ๅ„ชๅ…ˆๆคœ็ดขใฎๅฎŸ่ฃ…ใ‚’็คบใ—ใพใ™ใ€‚

 using System; using System.Collections.Generic; public class Graph<Location> { //        string, //      NameValueCollection public Dictionary<Location, Location[]> edges = new Dictionary<Location, Location[]>(); public Location[] Neighbors(Location id) { return edges[id]; } }; class BreadthFirstSearch { static void Search(Graph<string> graph, string start) { var frontier = new Queue<string>(); frontier.Enqueue(start); var visited = new HashSet<string>(); visited.Add(start); while (frontier.Count > 0) { var current = frontier.Dequeue(); Console.WriteLine("Visiting {0}", current); foreach (var next in graph.Neighbors(current)) { if (!visited.Contains(next)) { frontier.Enqueue(next); visited.Add(next); } } } } static void Main() { Graph<string> g = new Graph<string>(); g.edges = new Dictionary<string, string[]> { { "A", new [] { "B" } }, { "B", new [] { "A", "C", "D" } }, { "C", new [] { "A" } }, { "D", new [] { "E", "A" } }, { "E", new [] { "B" } } }; Search(g, "A"); } } 

ใ“ใ‚Œใฏใ€้‡ใฟไป˜ใใฎใ‚จใƒƒใ‚ธใ‚’ๆŒใคใ‚ฐใƒชใƒƒใƒ‰ใ‚’่กจใ™ใ‚ฐใƒฉใƒ•ใงใ™๏ผˆๅ‰ใฎ่จ˜ไบ‹ใฎๆฃฎใจๅฃใฎไพ‹๏ผ‰๏ผš

 using System; using System.Collections.Generic; //  A*   WeightedGraph    L,   ** //   .       . public interface WeightedGraph<L> { double Cost(Location a, Location b); IEnumerable<Location> Neighbors(Location id); } public struct Location { //   :   Equals  , //     . ,     //  Equals  GetHashCode. public readonly int x, y; public Location(int x, int y) { this.x = x; this.y = y; } } public class SquareGrid : WeightedGraph<Location> { //   :      , //    , ,    //     . public static readonly Location[] DIRS = new [] { new Location(1, 0), new Location(0, -1), new Location(-1, 0), new Location(0, 1) }; public int width, height; public HashSet<Location> walls = new HashSet<Location>(); public HashSet<Location> forests = new HashSet<Location>(); public SquareGrid(int width, int height) { this.width = width; this.height = height; } public bool InBounds(Location id) { return 0 <= id.x && id.x < width && 0 <= id.y && id.y < height; } public bool Passable(Location id) { return !walls.Contains(id); } public double Cost(Location a, Location b) { return forests.Contains(b) ? 5 : 1; } public IEnumerable<Location> Neighbors(Location id) { foreach (var dir in DIRS) { Location next = new Location(id.x + dir.x, id.y + dir.y); if (InBounds(next) && Passable(next)) { yield return next; } } } } public class PriorityQueue<T> { //       ,    //     .      //      C#: https://github.com/dotnet/corefx/issues/574 // //     ,     : // * https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp // * http://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx // * http://xfleury.imtqy.com/graphsearch.html // * http://stackoverflow.com/questions/102398/priority-queue-in-net private List<Tuple<T, double>> elements = new List<Tuple<T, double>>(); public int Count { get { return elements.Count; } } public void Enqueue(T item, double priority) { elements.Add(Tuple.Create(item, priority)); } public T Dequeue() { int bestIndex = 0; for (int i = 0; i < elements.Count; i++) { if (elements[i].Item2 < elements[bestIndex].Item2) { bestIndex = i; } } T bestItem = elements[bestIndex].Item1; elements.RemoveAt(bestIndex); return bestItem; } } /*   :      Python   *  ,     .   C++ *     typedef,     int, double  *  .     C#    ,  *   double.   int,   ,   *    ,    ,  ,  *    . */ public class AStarSearch { public Dictionary<Location, Location> cameFrom = new Dictionary<Location, Location>(); public Dictionary<Location, double> costSoFar = new Dictionary<Location, double>(); // :   A*   Location //  Heuristic static public double Heuristic(Location a, Location b) { return Math.Abs(ax - bx) + Math.Abs(ay - by); } public AStarSearch(WeightedGraph<Location> graph, Location start, Location goal) { var frontier = new PriorityQueue<Location>(); frontier.Enqueue(start, 0); cameFrom[start] = start; costSoFar[start] = 0; while (frontier.Count > 0) { var current = frontier.Dequeue(); if (current.Equals(goal)) { break; } foreach (var next in graph.Neighbors(current)) { double newCost = costSoFar[current] + graph.Cost(current, next); if (!costSoFar.ContainsKey(next) || newCost < costSoFar[next]) { costSoFar[next] = newCost; double priority = newCost + Heuristic(next, goal); frontier.Enqueue(next, priority); cameFrom[next] = current; } } } } } public class Test { static void DrawGrid(SquareGrid grid, AStarSearch astar) { //   cameFrom for (var y = 0; y < 10; y++) { for (var x = 0; x < 10; x++) { Location id = new Location(x, y); Location ptr = id; if (!astar.cameFrom.TryGetValue(id, out ptr)) { ptr = id; } if (grid.walls.Contains(id)) { Console.Write("##"); } else if (ptr.x == x+1) { Console.Write("\u2192 "); } else if (ptr.x == x-1) { Console.Write("\u2190 "); } else if (ptr.y == y+1) { Console.Write("\u2193 "); } else if (ptr.y == y-1) { Console.Write("\u2191 "); } else { Console.Write("* "); } } Console.WriteLine(); } } static void Main() { //  " 4"    var grid = new SquareGrid(10, 10); for (var x = 1; x < 4; x++) { for (var y = 7; y < 9; y++) { grid.walls.Add(new Location(x, y)); } } grid.forests = new HashSet<Location> { new Location(3, 4), new Location(3, 5), new Location(4, 1), new Location(4, 2), new Location(4, 3), new Location(4, 4), new Location(4, 5), new Location(4, 6), new Location(4, 7), new Location(4, 8), new Location(5, 1), new Location(5, 2), new Location(5, 3), new Location(5, 4), new Location(5, 5), new Location(5, 6), new Location(5, 7), new Location(5, 8), new Location(6, 2), new Location(6, 3), new Location(6, 4), new Location(6, 5), new Location(6, 6), new Location(6, 7), new Location(7, 3), new Location(7, 4), new Location(7, 5) }; //  A* var astar = new AStarSearch(grid, new Location(1, 4), new Location(8, 5)); DrawGrid(grid, astar); } } 

4ๆœ€้ฉๅŒ–


่จ˜ไบ‹ใฎใ‚ณใƒผใƒ‰ใ‚’ไฝœๆˆใ™ใ‚‹ใจใใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚ˆใ‚Šใ‚‚ๅ˜็ด”ใ•ใจ้ฉ็”จๆ€งใซๆณจ็›ฎใ—ใพใ—ใŸใ€‚ๆœ€ๅˆใซใ‚ณใƒผใƒ‰ใ‚’ๆฉŸ่ƒฝใ•ใ›ใฆใ‹ใ‚‰ใ€้€Ÿๅบฆใ‚’ๆœ€้ฉๅŒ–ใ—ใพใ™ใ€‚็งใŒๅฎŸ้š›ใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงไฝฟ็”จใ—ใŸๅคšใใฎๆœ€้ฉๅŒ–ใฏใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซๅ›บๆœ‰ใฎใ‚‚ใฎใงใ‚ใ‚‹ใŸใ‚ใ€ๆœ€้ฉใชใ‚ณใƒผใƒ‰ใ‚’็คบใ™ไปฃใ‚ใ‚Šใซใ€็‹ฌ่‡ชใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซๅฎŸ่ฃ…ใงใใ‚‹ใ„ใใคใ‹ใฎใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ๆไพ›ใ—ใพใ™ใ€‚

4.1ใ‚ซใ‚ฆใƒณใƒˆ


ๅฏ่ƒฝใชๆœ€ๅคงใฎๆœ€้ฉๅŒ–ใฏใ€ใƒŽใƒผใƒ‰ใฎๆ•ฐใ‚’ๆธ›ใ‚‰ใ™ใ“ใจใงใ™ใ€‚ๆŽจๅฅจไบ‹้ …1๏ผšใ‚ฐใƒชใƒƒใƒ‰ใฎใƒžใƒƒใƒ—ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€ใ‚ฐใƒชใƒƒใƒ‰ใซๅŸบใฅใ„ใฆใ„ใชใ„ใƒ‘ใ‚นๆคœ็ดขใ‚ฐใƒฉใƒ•ใ‚’้ฉ็”จใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใ‚Œใฏๅธธใซๅฏ่ƒฝใจใ„ใ†ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใ“ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฏๆคœ่จŽใ™ใ‚‹ไพกๅ€คใŒใ‚ใ‚Šใพใ™ใ€‚

ใ‚ฐใƒฉใƒ•ใŒๅ˜็ด”ใชๆง‹้€ ๏ผˆใ‚ฐใƒชใƒƒใƒ‰ใชใฉ๏ผ‰ใงใ‚ใ‚‹ๅ ดๅˆใ€้–ขๆ•ฐใฎ่ฟ‘ๅ‚ใ‚’่จˆ็ฎ—ใ—ใพใ™ใ€‚ใ‚ˆใ‚Š่ค‡้›‘ใชๆง‹้€ ๏ผˆใ‚ฐใƒชใƒƒใƒ‰ใชใ—ใ€ใพใŸใฏ่ฟท่ทฏใฎใ‚ˆใ†ใซๅคšๆ•ฐใฎๅฃใŒใ‚ใ‚‹ใ‚ฐใƒชใƒƒใƒ‰๏ผ‰ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ใƒ‡ใƒผใ‚ฟๆง‹้€ ใซ่ฟ‘ๅ‚ใ‚’ไฟๅญ˜ใ—ใพใ™ใ€‚

่ฟ‘้šฃใฎ้…ๅˆ—ใ‚’ๅ†ๅˆฉ็”จใ™ใ‚‹ใ“ใจใซใ‚ˆใ‚Šใ€ใ‚ณใƒ”ใƒผๆ“ไฝœใ‚’ไฟๅญ˜ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ๆฏŽๅ›žใƒชใ‚ฟใƒผใƒณใ‚’ๅฎŸ่กŒใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€ๆคœ็ดขใ‚ณใƒผใƒ‰ใงไธ€ๅบฆ้ธๆŠžใ—ใฆใ€ใ‚ฐใƒฉใƒ•ใฎใƒใ‚คใƒใƒผใƒกใ‚ฝใƒƒใƒ‰ใซๆธกใ—ใพใ™ใ€‚

4.2ใ‚ญใƒฅใƒผ


ๅน…ๅ„ชๅ…ˆๆคœ็ดขใงใฏใ€ไป–ใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใงไฝฟ็”จใ•ใ‚Œใ‚‹ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใงใฏใชใใ€้€šๅธธใฎใ‚ญใƒฅใƒผใŒไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ใ‚ญใƒฅใƒผใฏใ€ๅ„ชๅ…ˆใ‚ญใƒฅใƒผใ‚ˆใ‚Šใ‚‚้ซ˜้€Ÿใง็ฐกๅ˜ใงใ™ใ€‚ไป–ใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏใ€ใ‚ˆใ‚Šๅฐ‘ใชใ„ใƒŽใƒผใƒ‰ใ‚’่ชฟในใพใ™ใ€‚ใปใจใ‚“ใฉใฎใ‚ฒใƒผใƒ ใ‚ซใƒผใƒ‰ใงใฏใ€่ชฟๆŸปใ™ใ‚‹ใƒŽใƒผใƒ‰ใฎๆ•ฐใ‚’ๆธ›ใ‚‰ใ™ใ“ใจใฏใ€ไป–ใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’้…ใใ™ใ‚‹ไพกๅ€คใŒใ‚ใ‚Šใพใ™ใ€‚ใŸใ ใ—ใ€ใ‚ใพใ‚Š็ฏ€็ด„ใงใใชใ„ใ‚ซใƒผใƒ‰ใ‚‚ใ‚ใ‚‹ใŸใ‚ใ€ๅน…ใฎๆคœ็ดขใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ใŠๅ‹งใ‚ใ—ใพใ™ใ€‚

ใ‚ญใƒฅใƒผใฎๅ ดๅˆใฏใ€ไปฃใ‚ใ‚Šใซdeque้…ๅˆ—ใ‚’ไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ dequeใฏใ€ใฉใกใ‚‰ใฎๅดใ‹ใ‚‰ใงใ‚‚ใ™ใฐใ‚„ใๆŒฟๅ…ฅใŠใ‚ˆใณๅ‰Š้™คใงใใ‚‹ๆฉŸ่ƒฝใ‚’ๆไพ›ใ—ใพใ™ใŒใ€้…ๅˆ—ใฏไธ€ๆ–นใฎ็ซฏใ‹ใ‚‰ใฎใฟ้ซ˜้€Ÿใงใ™ใ€‚ Pythonใงใฏใ€collections.dequeใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ C ++ใงใฏใ€dequeใ‚ณใƒณใƒ†ใƒŠใ‚’ๆคœ่จŽใ—ใฆใใ ใ•ใ„ใ€‚ใŸใ ใ—ใ€ๅน…ๅ„ชๅ…ˆๆคœ็ดขใงใฏใ‚ญใƒฅใƒผใ‚‚ๅฟ…่ฆใ‚ใ‚Šใพใ›ใ‚“ใ€‚2ใคใฎใƒ™ใ‚ฏใ‚ฟใƒผใ‚’ไฝฟ็”จใ—ใฆใ€ไธ€ๆ–นใŒ็ฉบใฎใจใใซใใ‚Œใ‚‰ใ‚’ๅˆ‡ใ‚Šๆ›ฟใˆใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚

ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฎๅ ดๅˆใ€้…ๅˆ—ใพใŸใฏใ‚ฝใƒผใƒˆใ•ใ‚ŒใŸ้…ๅˆ—ใงใฏใชใใ€ใƒใ‚คใƒŠใƒชใƒ’ใƒผใƒ—ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ใƒใ‚คใƒŠใƒชใƒ’ใƒผใƒ—ใฏใ€ๆŒฟๅ…ฅใจๅ‰Š้™คใ‚’ใ™ใฐใ‚„ใ่กŒใ†ๆฉŸ่ƒฝใ‚’ๆไพ›ใ—ใพใ™ใŒใ€้…ๅˆ—ใฏ1ใคใฎ็‚นใง้ซ˜้€Ÿใงใ™ใ€‚ Pythonใงใฏใ€heapqใฎไฝฟ็”จใ‚’ใŠๅ‹งใ‚ใ—ใพใ™ใ€‚ C ++ใงใฏใ€priority_queueใ‚ณใƒณใƒ†ใƒŠใ‚’่ฉฆใ—ใฆใใ ใ•ใ„ใ€‚

Pythonใงใฏใ€ไธŠใง็คบใ—ใŸQueueใŠใ‚ˆใณPriorityQueueใ‚ฏใƒฉใ‚นใฏ้žๅธธใซๅ˜็ด”ใชใฎใงใ€ๆคœ็ดขใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใซใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๅŸ‹ใ‚่พผใ‚€ใ“ใจใŒใงใใพใ™ใ€‚ใ“ใ‚ŒใงใŸใใ•ใ‚“ๅ‹ใฆใ‚‹ใ‹ใฉใ†ใ‹ใฏใ‚ใ‹ใ‚Šใพใ›ใ‚“ใŒใ€ใƒ†ใ‚นใƒˆใ™ใ‚‹ไพกๅ€คใฏใ‚ใ‚Šใพใ™ใ€‚ C ++ใƒใƒผใ‚ธใƒงใƒณใŒๅŸ‹ใ‚่พผใพใ‚Œใพใ™ใ€‚

ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใงใฏใ€ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฎๅ„ชๅ…ˆๅบฆใŒ2ๅ›žไฟๅญ˜ใ•ใ‚Œใพใ™ใ€‚1ๅ›žใฏๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใซใ€2็•ช็›ฎใฏ2็•ช็›ฎใซไฟๅญ˜ใ•ใ‚Œใ‚‹cost_so_farใŸใ‚ใ€ใฉใ“ใ‹ใ‚‰ใงใ‚‚ๅ„ชๅ…ˆๅบฆใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใ‚’ไฝœๆˆใงใใพใ™ใ€‚ไพกๅ€คใŒใ‚ใ‚‹ใ‹ใฉใ†ใ‹ใฏใ‚ใ‹ใ‚Šใพใ›ใ‚“ใ€‚

ๆจ™ๆบ–ใฎใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎๅฎŸ่ฃ…ใงใฏใ€ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใฎๅ„ชๅ…ˆๅบฆใฎๅค‰ๆ›ดใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ใŸใ ใ—ใ€ๅ„ชๅ…ˆๅบฆใ‚’ๅค‰ๆ›ดใ—ใชใ„ใจใฉใ†ใชใ‚Šใพใ™ใ‹๏ผŸใใฎ็ตๆžœใ€ใใ“ใซ้‡่ค‡ใ—ใŸ่ฆ็ด ใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ใŸใ ใ—ใ€ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏๅผ•ใ็ถšใๆฉŸ่ƒฝใ—ใพใ™ใ€‚ๅฝผใฏๅฟ…่ฆไปฅไธŠใซใ„ใใคใ‹ใฎใƒใ‚คใƒณใƒˆใ‚’ๅ†่จชใ—ใพใ™ใ€‚ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใซใฏๅฟ…่ฆไปฅไธŠใฎ่ฆ็ด ใŒๅซใพใ‚Œใ‚‹ใŸใ‚ใ€้€ŸๅบฆใŒไฝŽไธ‹ใ—ใพใ™ใŒใ€ๅ„ชๅ…ˆๅบฆใฎๅค‰ๆ›ดใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ใƒ‡ใƒผใ‚ฟๆง‹้€ ใ‚‚ใ€่ฆ็ด ใŒๅคšใ„ใŸใ‚ใซ้€ŸๅบฆใŒไฝŽไธ‹ใ—ใพใ™ใ€‚Chenใ€Chaudheryใ€Ramachandranใ€Lan Rocheใ€Tongaใซใ‚ˆใ‚‹ใ€ŒPriority Queues and Dijkstra's Algorithmใ€ใฎ็ ”็ฉถใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใฎ็ ”็ฉถใงใฏใ€ใƒ’ใƒผใƒ—ใจใใฎไป–ใฎใƒ‡ใƒผใ‚ฟๆง‹้€ ใฎใƒšใ‚ขใƒชใƒณใ‚ฐใ‚’่€ƒๆ…ฎใ™ใ‚‹ใ“ใจใ‚‚ๆŽจๅฅจใ—ใฆใ„ใพใ™ใ€‚

ใƒใ‚คใƒŠใƒชใƒ’ใƒผใƒ—ใฎไปฃใ‚ใ‚Šใซไฝ•ใ‹ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’่€ƒใˆใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๆœ€ๅˆใซๅขƒ็•Œใฎใ‚ตใ‚คใ‚บใจๅ„ชๅ…ˆ้ †ไฝใŒๅค‰ๆ›ดใ•ใ‚Œใ‚‹้ ปๅบฆใ‚’ๆธฌๅฎšใ—ใพใ™ใ€‚ใ‚ณใƒผใƒ‰ใฎใƒ—ใƒญใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใ€ๅ„ชๅ…ˆๅบฆใ‚ญใƒฅใƒผใŒใƒœใƒˆใƒซใƒใƒƒใ‚ฏใซใชใฃใฆใ„ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’็ขบ่ชใ—ใพใ™ใ€‚

ๆœ‰ๆœ›ใชๆ–นๅ‘ๆ€งใฏใƒ‡ใƒผใ‚ฟใฎใ‚ฐใƒซใƒผใƒ—ๅŒ–ใ€‚ใ‚ญใƒผใŒๆ•ดๆ•ฐๅ€คใงใ‚ใ‚‹ๅ ดๅˆใ€ใƒ–ใƒญใƒƒใ‚ฏใ‚ฝใƒผใƒˆใจใƒ“ใƒƒใƒˆๅ˜ไฝใ‚ฝใƒผใƒˆใŒใ‚ฏใ‚คใƒƒใ‚ฏใ‚ฝใƒผใƒˆใฎไพฟๅˆฉใชไปฃๆ›ฟๆ‰‹ๆฎตใงใ‚ใ‚‹ใ‚ˆใ†ใซใ€ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใจA *ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎๅ ดๅˆใ€็Šถๆณใฏใ•ใ‚‰ใซ่‰ฏใใชใ‚Šใพใ™ใ€‚ใƒ€ใ‚คใ‚ฏใ‚นใƒˆใƒฉใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฎๅ„ชๅ…ˆ้ †ไฝใฏ้žๅธธใซไฝŽใ„ใงใ™ใ€‚ใ‚ญใƒฅใƒผๅ†…ใฎๆœ€ๅฐ่ฆ็ด ใŒๅ„ชๅ…ˆใ•ใ‚Œใ‚‹ๅ ดๅˆใฏfใ€ๆฌกใซไธ€็•ชไธŠใฎ่ฆ็ด ใŒๅ„ชๅ…ˆๆœ‰ใ—f+eใ€eใ‚จใƒƒใ‚ธใฎๆœ€ๅคง้‡้‡- ใ€‚ๆฃฎใฎไพ‹ใงใฏใ€ใƒ•ใ‚ฃใƒณ1ใจ5ใ‚ญใƒฅใƒผๅ†…ใฎใ™ในใฆใฎๅ„ชๅ…ˆ้ †ไฝใฎ้–“ใซใชใ‚‹ใจใ€ใ“ใฎๆ‰‹ๆฎตใฎ้‡้‡ๆŒใคfใจใ—ใพใ™f+5ใ€‚ใใ‚Œใ‚‰ใฏใ™ในใฆๆ•ดๆ•ฐใงใ‚ใ‚‹ใŸใ‚ใ€6ใคใฎ็•ฐใชใ‚‹ๅ„ชๅ…ˆ้ †ไฝใŒใ‚ใ‚Šใพใ™ใ€‚ใ€‚6ใคใฎใƒ–ใƒญใƒƒใ‚ฏใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใ€ไฝ•ใ‚‚ใ‚ฝใƒผใƒˆใ—ใชใ„ใ“ใจใ‚‚ใงใใพใ™๏ผ*ใฏใ‚ˆใ‚Šๅน…ๅบƒใ„ๅ„ชๅ…ˆ้ †ไฝใ‚’ไฝœๆˆใ—ใพใ™ใŒใ€ใใ‚Œใงใ‚‚ใ“ใฎๆ–นๆณ•ใฏๆคœ่จŽใ™ใ‚‹ไพกๅ€คใŒใ‚ใ‚Šใพใ™ใ€‚ใพใŸใ€ใ‚ˆใ‚Šๅบƒ็ฏ„ใช็Šถๆณใซๅฏพๅ‡ฆใงใใ‚‹ใ‚ฐใƒซใƒผใƒ—ๅŒ–ใธใฎใ‚ˆใ‚Š่ˆˆๅ‘ณๆทฑใ„ใ‚ขใƒ—ใƒญใƒผใƒใŒใ‚ใ‚Šใพใ™ใ€‚

ๅ„ชๅ…ˆใ‚ญใƒฅใƒผใฎใƒ‡ใƒผใ‚ฟๆง‹้€ ใซ้–ขใ™ใ‚‹ๅˆฅใฎ่จ˜ไบ‹ใŒใ‚ใ‚Šใพใ™ใ€‚

4.3ๆคœ็ดข


ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใซใ‚ˆใ‚Šใ€CPUใฎ่ค‡้›‘ใ•ใจๆ™‚้–“ใŒๆถˆ่ฒปใ•ใ‚Œใพใ™ใ€‚ใŸใ ใ—ใ€ใ“ใ“ใงใฎ็›ฎๆจ™ใฏใ€ใ‚ˆใ‚Šๅฐ‘ใชใ„ใƒŽใƒผใƒ‰ใ‚’่ชฟๆŸปใ™ใ‚‹ใ“ใจใงใ™ใ€‚ไธ€้ƒจใฎใƒžใƒƒใƒ—๏ผˆ่ฟท่ทฏใชใฉ๏ผ‰ใงใฏใ€ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใฏๅคšใใฎๆƒ…ๅ ฑใ‚’่ฟฝๅŠ ใ—ใชใ„ๅ ดๅˆใŒใ‚ใ‚Šใ€ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใ‚’ไฝฟ็”จใ—ใชใ„ๅ˜็ด”ใชใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ไฝฟ็”จใ™ใ‚‹ๆ–นใŒ้ฉๅˆ‡ใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚

ๆ•ดๆ•ฐๅ€คใ‚’ไฝฟ็”จใ—ใฆใฎใƒใ‚คใƒณใƒˆใจใ—ใฆใ‚ใชใŸใฎใ‚ฐใƒฉใƒ•ใฏใ€ใใฎๅพŒใ€ไฝฟ็”จใฎๅฏ่ƒฝๆ€งใ‚’ๆคœ่จŽใ—ใŸๅ ดๅˆใฏcost_so_farใ€visitedใ€came_fromใชใฉใƒใƒƒใ‚ทใƒฅใƒ†ใƒผใƒ–ใƒซใงใฏใชใใ€ๅ˜็ด”ใช้…ๅˆ—ใ€‚ใ“ใ‚Œvisitedใฏใƒ–ใƒผใƒซ้…ๅˆ—ใงใ‚ใ‚‹ใŸใ‚ใ€ใƒ“ใƒƒใƒˆใƒ™ใ‚ฏใƒˆใƒซใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ใ™ในใฆใฎ่ญ˜ๅˆฅๅญใฎใƒ“ใƒƒใƒˆใƒ™ใ‚ฏใƒˆใƒซใ‚’ๅˆๆœŸๅŒ–ใ—ใพใ™ใŒcost_so_farใ€came_fromๅˆๆœŸๅŒ–ใ•ใ‚Œใชใ„ใพใพใซใ—ใพใ™๏ผˆ่จ€่ชžใง่จฑๅฏใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆ๏ผ‰ใ€‚ใใฎๅพŒใ€ๆœ€ๅˆใฎ่จชๅ•ๆ™‚ใซใฎใฟๅˆๆœŸๅŒ–ใ—ใพใ™ใ€‚

ไธ€ๅบฆใซ1ใคใฎๆคœ็ดขใฎใฟใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใ€ๆฌกใฎๅ‘ผใณๅ‡บใ—ใง้™็š„ใซใƒ‡ใƒผใ‚ฟๆง‹้€ ใ‚’ๆŠฝๅ‡บใ—ใฆๅ†ๅˆฉ็”จใงใใพใ™ใ€‚ๅ…ฅๅŠ›ใงๅˆๆœŸๅŒ–ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€ๅ‡บๅŠ›ใงใƒชใ‚ปใƒƒใƒˆใ—ใพใ™ใ€‚้…ๅˆ—ใ‚’ไฝฟ็”จใ—ใฆใ€ๅค‰ๆ›ดใ™ใ‚‹ใƒใ‚คใƒณใƒˆใ‚’่ฟฝ่ทกใ—ใ€ๅค‰ๆ›ดใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚ใŸใจใˆใฐvisited[]ใ€1000ใƒŽใƒผใƒ‰็”จใซๅˆๆœŸๅŒ–ใ•ใ‚ŒใŸ้…ๅˆ—ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใŒใ€ใปใจใ‚“ใฉใฎๆคœ็ดขใƒ—ใƒญใ‚ปใ‚นใŒ100ใƒŽใƒผใƒ‰ๆœชๆบ€ใ‚’่จชๅ•ใ™ใ‚‹ๅ ดๅˆใ€้–ขๆ•ฐใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ใจใใซ1000ใƒŽใƒผใƒ‰ใ™ในใฆใ‚’ๅ†ๅˆๆœŸๅŒ–ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚น้…ๅˆ—ใ‚’ๅค‰ๆ›ดใ—ใ€้–ขๆ•ฐใ‚’็ต‚ไบ†ใ™ใ‚‹ใจใใซใ“ใ‚Œใ‚‰ใฎ100ใƒŽใƒผใƒ‰ใฎใฟใ‚’ๅค‰ๆ›ดใงใใพใ™ใ€‚็„กๅŠนใช

*ใ‚’ไฝฟ็”จใ™ใ‚‹ไบบใ‚‚ใ„ใพใ™๏ผˆ้Žๅคง่ฉ•ไพก๏ผ‰ใƒ’ใƒฅใƒผใƒชใ‚นใƒ†ใ‚ฃใƒƒใ‚ฏใ€‚ใใ‚Œใฏ็†ใซใ‹ใชใฃใฆใ„ใ‚‹ใ‚ˆใ†ใงใ™ใ€‚ใŸใ ใ—ใ€ใ“ใ‚Œใ‚‰ใฎๅฎŸ่ฃ…ใซใคใ„ใฆใฏๆ…Ž้‡ใซๆคœ่จŽใ—ใพใ›ใ‚“ใงใ—ใŸใ€‚ๆ—ขใซ่จชๅ•ใ—ใŸไธ€้ƒจใฎ่ฆ็ด ใฏใ€ๆ—ขใซๅ›ฝๅขƒใ‹ใ‚‰ๅ‰Š้™คใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใงใ‚‚ใ€ๅ†ๅบฆ่จชๅ•ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจๆ€ใ„ใพใ™๏ผˆ็ขบใ‹ใงใฏใ‚ใ‚Šใพใ›ใ‚“๏ผ‰ใ€‚

ๅฎŸ่ฃ…ใซใ‚ˆใฃใฆใฏใ€ๆ–ฐใ—ใ„ใƒŽใƒผใƒ‰ใŒๆ—ขใซ้–‹ใ„ใฆใ„ใ‚‹ใ‚ปใƒƒใƒˆใซๆ—ขใซๆŒฟๅ…ฅใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใงใ‚‚ใ€ๅธธใซๆŒฟๅ…ฅใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒŽใƒผใƒ‰ใŒๆ—ขใซใ‚ชใƒผใƒ—ใƒณใ‚ปใƒƒใƒˆใซใ‚ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’็ขบ่ชใ™ใ‚‹ใ‚ณใ‚นใƒˆใฎใ‹ใ‹ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅ›ž้ฟใงใใพใ™ใ€‚ใŸใ ใ—ใ€ๅŒๆ™‚ใซใ€้–‹ใ„ใฆใ„ใ‚‹ใ‚ปใƒƒใƒˆใŒๅคงใใ/้…ใใชใ‚Šใ€ใใฎ็ตๆžœใ€ๅฟ…่ฆไปฅไธŠใฎใƒŽใƒผใƒ‰ใ‚’่ฉ•ไพกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ‚ชใƒผใƒ—ใƒณใ‚ปใƒƒใƒˆใฎใƒใ‚งใƒƒใ‚ฏใซใ‚ณใ‚นใƒˆใŒใ‹ใ‹ใ‚‹ๅ ดๅˆใฏใ€ใŠใใ‚‰ใใ“ใฎใ‚ขใƒ—ใƒญใƒผใƒใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใŸใ ใ—ใ€ๆ็คบใ—ใŸใ‚ณใƒผใƒ‰ใงใฏใ€ใƒใ‚งใƒƒใ‚ฏใ‚’ๅฎ‰ใใ—ใ€ใ“ใฎใ‚ขใƒ—ใƒญใƒผใƒใฏไฝฟ็”จใ—ใพใ›ใ‚“ใ€‚

ใ„ใใคใ‹ใฎๅฎŸ่ฃ…ใงใฏๆ–ฐใ—ใ„ใƒŽใƒผใƒ‰ใŒใ‚ชใƒผใƒ—ใƒณใ‚ปใƒƒใƒˆๅ†…ใฎๆ—ขๅญ˜ใฎใƒŽใƒผใƒ‰ใ‚ˆใ‚Šใ‚‚ๅ„ชใ‚Œใฆใ„ใ‚‹ใ‹ใฉใ†ใ‹ใฏใƒใ‚งใƒƒใ‚ฏใ•ใ‚Œใพใ›ใ‚“ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๆฝœๅœจ็š„ใซใ‚ณใ‚นใƒˆใฎใ‹ใ‹ใ‚‹ๆคœ่จผใŒๅ›ž้ฟใ•ใ‚Œใพใ™ใ€‚ใŸใ ใ—ใ€ใ“ใ‚Œใซใ‚ˆใ‚Šใ‚จใƒฉใƒผใŒ็™บ็”Ÿใ™ใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ไธ€้ƒจใฎ็จฎ้กžใฎใ‚ซใƒผใƒ‰ใงใฏใ€ใ“ใฎใƒใ‚งใƒƒใ‚ฏใ‚’ใ‚นใ‚ญใƒƒใƒ—ใ™ใ‚‹ใจๆœ€็Ÿญ็ตŒ่ทฏใŒ่ฆ‹ใคใ‹ใ‚Šใพใ›ใ‚“ใ€‚ๆ็คบใ—ใŸใ‚ณใƒผใƒ‰ใงใฏใ€ใ“ใฎใƒใ‚งใƒƒใ‚ฏใ‚’ๅฎŸ่กŒใ—ใพใ™๏ผˆnew_cost < cost_so_far๏ผ‰ใ€‚็งใŒcost_so_farๅฎ‰ใ„ๆคœ็ดขใ‚’ใ—ใŸใฎใงใ€ใ“ใฎใƒใ‚งใƒƒใ‚ฏใฏๅฎ‰ใ„ใงใ™ใ€‚

5ใƒˆใƒฉใƒ–ใƒซใ‚ทใƒฅใƒผใƒ†ใ‚ฃใƒณใ‚ฐ


5.1้–“้•ใฃใŸใƒ‘ใ‚น


ๆœ€็Ÿญใƒ‘ใ‚นใ‚’ๅ–ๅพ—ใงใใชใ„ๅ ดๅˆใฏใ€ๆฌกใฎใƒใ‚งใƒƒใ‚ฏใ‚’่ฉฆใ—ใฆใใ ใ•ใ„ใ€‚


5.2


ใปใจใ‚“ใฉใฎๅ ดๅˆใ€ใ‚ฐใƒชใƒƒใƒ‰ใงA *ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใใซใ€ๅฝผใ‚‰ใฏ็งใซ่ณชๅ•ใ‚’ใ—ใพใ™๏ผšใชใœใƒ‘ใ‚นใฏใพใฃใ™ใใซ่ฆ‹ใˆใชใ„ใฎใงใ™ใ‹๏ผŸใ‚ฐใƒชใƒƒใƒ‰ใซๆฒฟใฃใŸใ™ในใฆใฎๅ‹•ใใฎใ‚ณใ‚นใƒˆใŒ็ญ‰ใ—ใ„ใ“ใจใ‚’A *ใซไผใˆใ‚‹ใจใ€ๅŒใ˜้•ทใ•ใฎๅคšใใฎๆœ€็Ÿญ็ตŒ่ทฏใŒๅพ—ใ‚‰ใ‚Œใ€ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏใใ‚Œใ‚‰ใฎ1ใคใ‚’ใƒฉใƒณใƒ€ใƒ ใซ้ธๆŠžใ—ใพใ™ใ€‚ใƒ‘ใ‚นใฏ็Ÿญใ„ใงใ™ใŒใ€่ฆ‹ๆ „ใˆใŒใ‚ˆใใ‚ใ‚Šใพใ›ใ‚“ใ€‚


6


Source: https://habr.com/ru/post/J331220/


All Articles