±à¼ÍƼö: |
±¾ÎÄÖУ¬ÎÒÃÇ´Ó¹ã¶ÈÓÅÏÈËã·¨³ö·¢£¬Ò»²½²½¸ÄÁ¼Ëã·¨Ö±µ½Òý³öA*Ëã·¨£¬²¢½éÉÜÁËA*Ëã·¨ÈçºÎ¿Ë·þÁËÆô·¢Ê½ËÑË÷Óöµ½µÄÎÊÌ⣬ϣÍû¶ÔÄúµÄѧϰÓÐËù°ïÖú¡£
±¾ÎÄÀ´×ÔÓÚcsdn£¬ÓÉ»ðÁú¹ûÈí¼þAlice±à¼¡¢ÍƼö¡£ |
|
×î¶Ì·¾¶ËÑË÷ÊÇͨ¹ýËã·¨ÕÒµ½Ò»ÕÅͼ´ÓÆðµã£¨start£©µ½Öյ㣨goal£©Ö®¼äµÄ×î¶Ì·¾¶£¨path£©£¬ÎªÁ˼ò»¯£¬ÎÒÃÇÕâÀïʹÓ÷½¸ñͼ£¨¸Ãͼ¿ÉÒÔ¼òµ¥µØÓöþάÊý×éÀ´±íʾ£©£¬Èç϶¯Í¼Ëùʾ£¬ÆäÖдú±íÆðµã£¬´ú±íÖյ㡣
¹ã¶ÈÓÅÏÈËã·¨£¨Breadth-First-Search, BFS£©
¹ã¶ÈÓÅÏÈË㷨ʵ¼ÊÉÏÒѾÄܹ»ÕÒµ½×î¶Ì·¾¶£¬BFSͨ¹ýÒ»ÖÖ´ÓÆðµã¿ªÊ¼²»¶ÏÀ©É¢µÄ·½Ê½À´±éÀúÕû¸öͼ¡£¿ÉÒÔÖ¤Ã÷£¬Ö»Òª´ÓÆðµã¿ªÊ¼µÄÀ©É¢¹ý³ÌÄܹ»±éÀúµ½Öյ㣬ÄÇôÆðµãºÍÖÕµãÖ®¼äÒ»¶¨ÊÇÁ¬Í¨µÄ£¬Òò´ËËûÃÇÖ®¼äÖÁÉÙ´æÔÚÒ»Ìõ·¾¶£¬¶øÓÉÓÚBFS´ÓÖÐÐÄ¿ªÊ¼³Ê·ÅÉä×´À©É¢µÄÌØµã£¬ËüËùÕÒµ½µÄÕâÒ»Ìõ·¾¶¾ÍÊÇ×î¶Ì·¾¶£¬ÏÂͼÑÝʾÁËBFSµÄÀ©É¢¹ý³Ì£º

ÆäÖÐÓÉÈ«²¿À¶É«·½¿é×é³ÉµÄ¶ÓÁнÐ×öfrontier £¨²Î¿¼ÏÂÃæµÄBFS´úÂ룩
È»¶ø£¬BFSËÑË÷×î¶Ì·¾¶ÊµÔÚÌ«ÂýÁË£¬ÎªÁËÌá¸ßBFSµÄËÑË÷ЧÂÊ£¬½ÓÏÂÀ´ÎÒÃÇ´ÓBFSÒ»²½²½¸ÄÁ¼µ½A*Ëã·¨£¨ÆäÖеĴúÂëÖ÷ÒªÓÃÓÚ±í´ï˼·£¬¾àÀëʵ¼ÊÔËÐл¹È±²¿·Ösupport
code)
BFS´úÂ룺
frontier = Queue()
frontier.put(start)
visited = {}
visited[start] = True
while not frontier.empty():
current = frontier.get()
for next in graph.neighbors(current):
if next not in visited:
frontier.put(next)
visited[next] = True |
ËùÉæ¼°µ½µÄÖ÷ÒªÊý¾Ý½á¹¹:
graph£¬ÒªÕÒµ½Ò»ÕÅͼÖÐÁ½µãÖ®¼äµÄpath£¬ÎÒÃÇÐèÒªÒ»¸ö×î»ù±¾µÄgraphÊý¾Ý½á¹¹¡£ÔÚ±¾ÎÄÖУ¬ÎÒÃÇÖ»ÐèÒªµÃµ½Ä³Ò»µãµÄÁÚ½üµã£¬ÔÚÕâÀïÎÒÃǵĴúÂëµ÷ÓÃgraph.neighbors(current)£¬¸Ãº¯Êý·µ»ØµãcurrentÖÜΧµÄËùÓÐÁÚ½üµã¹¹³ÉµÄÒ»¸öÁÐ±í£¬ÓÉforÑ»·¿ÉÒÔ±éÀúÕâ¸öÁÐ±í¡£
queue ΪÁ˽âÊÍÓöÓÁеÄÔÒò£¬Çë¿´ÏÂͼ£¬¼ÙÉè´ËʱfrontierΪ¿Õ£¬currentµ±Ç°ÊÇAµã£¬ËüµÄneighbors½«·µ»ØB¡¢C¡¢D¡¢EËĸöµã£¬ÔÚ½«Õâ4¸öµã¶¼Ìí¼Óµ½frontierµ±ÖÐÒÔºó£¬ÏÂÒ»ÂÖwhileÑ»·£¬frontier.get()½«·µ»ØBµã£¨¸ù¾ÝFIFOÔÔò£¬Bµã×îÔçÈë¶Ó£¬Ó¦µ±×îÔç³ö¶Ó£©£¬´Ëʱµ÷ÓÃneighbors£¬·µ»ØA¡¢f¡¢g¡¢hËĸöµã£¬³ýÁËAµã£¬ÆäËû3¸öµãÓÖ±»Ìí¼Óµ½frontierµ±ÖÐÈ¥¡£ÔÙµ½ÏÂÒ»ÂÖÑ»·£¬´Ëʱfrontierµ±ÖÐÓÐC¡¢D¡¢f¡¢g¡¢hÕ⼸¸öµã£¬ÓÉÓÚ¶ÓÁеÄFIFOÔÔò£¬frontier.get()½«·µ»ØCµã¡£ÕâÑù¾Í±£Ö¤ÁËÕû¸öÀ©É¢¹ý³ÌÊÇÓɽüµ½Ô¶£¬ÓÉÄÚ¶øÍâµÄ£¬ÕâÒ²Êǹã¶ÈÓÅÏÈËÑË÷µÄÔÔò¡£¿ÉÒÔ¿´µ½£¬frontier.get()´Ó¶ÓÁÐÖÐÈ¡³öÒ»¸öÔªËØ£¨¸ÃÔªËØ½«´Ó¶ÓÁÐÖб»É¾³ý£©¡£¶øfrontier.put()½«currentµÄÁÚ½üµãÓÖÌí¼Ó½øÈ¥£¬Õû¸ö¹ý³Ì²»¶ÏÖØ¸´£¬Ö±µ½Í¼ÖеÄËùÓе㶼±»±éÀúÒ»±é¡£
visitedÁÐ±í£º½Ó×ÅÉÏÃæµÄÌÖÂÛ£¬graph.neighbors(A)½«·µ»ØB¡¢C¡¢D¡¢E
4¸öµã£¬ËæºóÕâ4¸öµã±»Ìí¼Óµ½frontierµ±ÖУ¬ÏÂÒ»ÂÖgraph.neighbors(B)½«·µ»ØA¡¢h¡¢f¡¢gËĸöµã£¬¶ø¼ÓÈë´ËʱAÔÙ±»Ìí¼Óµ½frontierµ±Öо͵¼Ö±éÀúÏÝÈëËÀÑ»·£¬ÎªÁ˱ÜÃâÕâÖÖ×´¿ö³öÏÖ£¬ÎÒÃÇÐèÒª½«ÒѾ±éÀú¹ýÁ˵ĵãÌí¼Óµ½visitedÁÐ±íµ±ÖУ¬Ö®ºóÔÚ½«µã·ÅÈëfrontier֮ǰ£¬Ê×ÏÈÅжϸõãÊÇ·ñÒѾÔÚvisitedÁÐ±íµ±ÖС£

ÏÂÃæµÄ¶¯Í¼¿ÉÒÔ¿´µ½Õû¸ö¹ã¶ÈÓÅÏÈËã·¨ÔËÐеÄÏêϸ¹ý³Ì£º

ÆäÖÐÂÌÉ«·½¿ò´ú±íneighborsËù·µ»ØµÄcurrentµãµÄÁÚ½üµã£¬À¶É«·½¿é´ú±íµ±Ç°frontier¶ÓÁÐÖеĵ㣬ÓÉÓÚ¶ÓÁÐÏȽøÏȳö(FIFO)µÄÌØµã£¬Ô½Ôç¼ÓÈë¶ÓÁеĵãµÄÐòºÅ£¨Í¼Öз½¿éµÄÊý×Ö£©Ô½Ð¡£¬Òò´ËÔ½Ôç±»while
not frontier.empty()Ñ»·ÖÐµÄ current = frontier.get()±éÀúµ½¡£
ÕÒµ½Â·Ïß
ÏÖÔÚÎÒÃǵÄËã·¨Äܹ»¶ÔËùÓÐµÄµã½øÐбéÀú£¬Ò²¾ÍÒâζ×ÅÒ»¶¨Äܹ»À©É¢µ½Ä¿±êµã£¬Òò´Ë´Ó¿ªÊ¼µ½ÖÕÖ¹µãµÄ·¾¶ÊÇ´æÔڵġ£ÎªÁËÉú³ÉÕâһ·¾¶£¬ÎÒÃÇÐèÒª¶ÔÀ©É¢µÄ¹ý³Ì½øÐмǼ£¬±£´æÃ¿Ò»¸öµãµÄÀ´Ô´£¨¸ÃµãÓÉÄÄÒ»¸öµãÀ©É¢¶øÀ´£©£¬×îºóͨ¹ýÕâЩ¼Ç¼½øÐлØËݼ´¿ÉµÃ³öÍêÕûµÄ·¾¶¡£½«visitedÊý×é¸ÄΪcame_from¡£±ÈÈç´ÓAÀ©É¢µ½B£¬Ôòcame_from[B]=A¡£ÓÐÁËÕâÑùµÄÏßË÷£¬ÎÒÃǾÍÄܹ»´ÓÖÕµã»ØËݵ½Æðµã¡£
frontier = Queue()
frontier.put()
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 |
ÏÂÃæµÄË㷨ͨ¹ýcame_fromÊý×éÀ´Éú³ÉpathµÄËã·¨£¬ÆäÖÐgoal±íʾÖյ㡣
current = goal
path = []
while current != start
path.append(current)
current = came_from[current]
path.append(start)
path.reverse() |
Ч¹ûÈçÏÂͼ£¬ÆäÖÐÿ¸ö·½¿éÉϵļýÍ·Ö¸ÏòËüµÄÀ´Ô´µã£¬×¢Òâ¹Û²ìËæ×ÅÖÕµãµÄ±ä»¯£¬ÈçºÎͨ¹ý¼ýÍ·µÄ»ØËݵõ½ÍêÕû·¾¶¡£

Ìáǰ½áÊø
ĿǰÎÒÃǵÄËã·¨»á±éÀúÕû¸öͼµÄÿһ¸öµã£¬»ØÏëÎÒÃÇ×î³õµÄÄ¿±ê£ºÕÒµ½´ÓÆðµãµ½ÖÕµãÖ®¼äµÄ·¾¶£¬Ö»ÐèÒª±éÀúµ½Öյ㼴¿É¡£ÎªÁ˼õÉÙÎÞÓù¦£¬ÎÒÃÇÉèÖÃÖÕÖ¹Ìõ¼þ£ºÒ»µ©±éÀúµ½goalÒÔºó£¬Í¨¹ýbreakÈÃÕû¸öË㷨ֹͣ¡£
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 |
À©É¢µÄ·½ÏòÐÔ
µ½ÁËÕâÒ»²½£¬Õû¸öBFSµÄ˼·ÒѾÍêÕûÁË£¬µ«Ä¿Ç°ËüµÄ±éÀú·½·¨ÈÔȻûÓÐÃ÷È·µÄÄ¿±ê£¬À©É¢³¯×ÅËùÓз½Ïòǰ½ø£¬Ê®·Ö´À±¿µÄ±éÀúÁËÒÔÆðµãΪÖÐÐĵÄÖÜΧÿһ¸ö·½¿é£¬Õâ²»¾ÍÊÇÇî¾ÙÂð£¿
ÔÚÉÏÃæµÄËã·¨ÔËÐйý³ÌÖУ¬frontier¶ÓÁÐÄÚ²¿Ò»°ã¶¼»á±£³Ö¼¸¸öµã£¨Ã¿´Îfrontier.get()ÄóöÀ´Ò»¸öµã£¬frontier.put()ÓÖ·Å»ØÈ¥Ò»¸öµã£©¡£¶øfrontier.get()·µ»ØÕâЩµãÖеÄÄÄÒ»¸ö¾ö¶¨ÁËÎÒÃǵÄÀ©É¢Ïò×ÅÄÄÒ»¸ö·½Ïò½øÐС£Ö®Ç°Õâ¸öº¯ÊýÖ»ÊǸù¾ÝqueueĬÈϵÄFIFOÔÔòÀ´½øÐУ¬Òò´Ë²úÉúÁË·øÉä×´µÄÀ©É¢·½Ê½£¬ÉÏÎÄÔÚ½éÉÜfrontierµÄʱºòÒѾ½âÊ͹ýÕâÒ»µã¡£
ÎÒÃÇÏëµ½£¬ÄÜ·ñÈÃÎÒÃǵÄÀ©É¢¹ý³ÌÓвàÖØ·½ÏòµØ½øÐÐÄØ£¿ ×¢Ò⣬ÆäʵÎÒÃÇʼÖÕÇå³þµØÖªµÀÆðʼµãºÍÖÕÖ¹µãµÄ×ø±ê£¬È´ÀË·ÑÁËÕâÌõÓмÛÖµµÄÐÅÏ¢¡£ÔÚfrontier.get()·µ»ØÁËfrontier¼¸¸öµãµ±ÖеÄÒ»¸ö£¬ÎªÁË¡°Óз½Ïò¡±µØ½øÐÐÀ©É¢£¬ÎÒÃÇÈÃfrontier·µ»ØÄǸö¿´ËƾàÀëÖÕµã×î½üµÄµã¡£ÓÉÓÚÎÒÃÇʹÓõÄÊÇ·½¸ñͼ£¬Ã¿¸öµã¶¼ÓÐ(x,y)×ø±ê£¬Í¨¹ýÁ½µãµÄ(x,y)×ø±ê¾Í¿ÉÒÔ¼ÆËãËüÃÇÖ®¼äµÄ¾àÀ룬ÕâÀï²ÉÓÃÂü¹þ¶Ù¾àÀëËã·¨£º
def heuristic(a,
b):
# ÕâÖÖ¾àÀë½Ð×öÂü¹þ¶Ù¾àÀ루Manhattan£©
return abs(a.x - b.x) + abs(a.y - b.y) |
Æô·¢Ê½µÄËÑË÷
½ÓÏÂÀ´ÎÒÃǸıäÔÀ´¶ÓÁеÄFIFOģʽ£¬¸ø²»Í¬µÄµã¼ÓÈëÓÅÏȼ¶£¬Ê¹ÓÃPriorityQueue£¬ÆäÖÐfrontier.put(next,priority)µÄµÚ¶þ¸ö²ÎÊýԽС£¬¸ÃµãµÄÓÅÏȼ¶Ô½¸ß£¬¿ÉÒÔÖªµÀ£¬¾àÀëÖÕµãµÄÂü¹þ¶Ù¾àÀëԽСµÄµã£¬»áÔ½Ôç´Ófrontier.get()µ±Öзµ»Ø¡£
frontier = PriorityQueue()
frontier.put(start, 0)
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:
priority = heuristic(goal, next)
frontier.put(next, priority)
came_from[next] = current |
ÏÂÃæ¾ÍÊÇÆô·¢Ê½ËÑË÷µÄЧ¹û£¬unbelievable!

µ½ÕâÀïÊDz»ÊÇÓÎÏ·¾Í½áÊøÁË£¿ Õâ²»¾Í¸ã¶¨À²£¬»¹ÒªA*×öʲô£¿ ÇÒÂý£¬Çë¿´ÏÂͼÖгöÏÖµÄÐÂÎÊÌ⣺

¿ÉÒÔ¿´µ½£¬ËäÈ»Æô·¢Ê½ËÑË÷±ÈBFS¸ü¿ìµÃ³ö½á¹û£¬µ«ËüËùÉú³ÉµÄ·¾¶²¢²»ÊÇ×îÓŵ쬯äÖгöÏÖÁËÒ»Ð©ÈÆÍä·µÄ×´¿ö¡£
´ÓÆðµãµ½ÖÕµã×Ü»á´æÔÚ¶àÌõ·¾¶£¬Ö®Ç°ÎÒÃÇͨ¹ývisited£¨ºóÀ´ÓÃcame_from£© Êý×éÀ´±ÜÃâÖØ¸´±éÀúͬһ¸öµã£¬È»¶øÕâµ¼ÖÂÁËÏÈÈëΪÖ÷µØ½«×îÔç±éÀú·¾¶µ±³É×î¶Ì·¾¶¡£ÎªÁ˼æ¹ËЧÂʺÍ×î¶Ì·¾¶£¬ÎÒÃÇÀ´¿´DijkstraËã·¨£¬ÕâÖÖËã·¨µÄÖ÷Ҫ˼ÏëÊÇ´Ó¶àÌõ·¾¶ÖÐÑ¡Ôñ×î¶ÌµÄÄÇÒ»Ìõ£ºÎÒÃǼǼÿ¸öµã´ÓÆðµã±éÀúµ½ËüËù»¨·ÑµÄµ±Ç°×îÉÙ³¤¶È£¬µ±ÎÒÃÇͨ¹ýÁíÍâÒ»Ìõ·¾¶ÔٴαéÀúµ½Õâ¸öµãµÄʱºò£¬ÓÉÓڸõãÒѾ±»±éÀú¹ýÁË£¨ÒѾ¼ÓÈëÁËcame_fromÊý×飩£¬ÎÒÃÇ´Ëʱ²»ÔÙÖ±½ÓÌø¹ý¸Ãµã£¬¶øÊDZȽÏÒ»ÏÂĿǰµÄ·¾¶ÊÇ·ñ±È¸Ãµã×î³õ±éÀúµÄ·¾¶»¨·Ñ¸üÉÙ£¬Èç¹ûÊÇÕâÑù£¬ÄǾͽ«¸ÃµãÄÉÈ뵽еķ¾¶µ±ÖÐÈ¥£¨Ð޸ĸõãÔÚcame_fromÖеÄÖµ£©¡£ÏÂÃæµÄ´úÂë¿ÉÒÔ¿´µ½ÕâÖֱ仯£¬ÎÒÃÇͨ¹ýά»¤cost_so_far¼Ç¼ÿ¸öµãµ½ÆðµãµÄµ±Ç°×î¶Ì·¾¶»¨·Ñ£¨³¤¶È£©£¬²¢½«ÕâÀïµÄcost×÷Ϊ¸ÃµãÔÚPriorityQueueÖеÄÓÅÏȼ¶¡£
Dijkstra:
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] + 1
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 |
Ò»·½Ã棬ÎÒÃÇÐèÒªËã·¨Óз½ÏòµØ½øÐÐÀ©É¢£¨Æô·¢Ê½£©£¬ÁíÒ»·½ÃæÎÒÃÇÐèÒªµÃµ½¾¡¿ÉÄÜ×î¶ÌµÄ·¾¶£¬Òò´ËA*¾Íµ®ÉúÁË£¬
Ëü½áºÏÁËDijkstraºÍÆô·¢Ê½Ëã·¨µÄÓŵ㣬ÒÔ´ÓÆðµãµ½¸ÃµãµÄ¾àÀë¼ÓÉϸõ㵽ÖÕµãµÄ¹À¼Æ¾àÀëÖ®ºÍ×÷Ϊ¸ÃµãÔÚQueueÖеÄÓÅÏȼ¶£¬ÏÂÃæÊÇA*Ëã·¨µÄ´úÂ룺
A*Ëã·¨
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] + 1
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 |
ÏÂÃæµÄͼչÏÖÁËA*Ëã·¨ÈçºÎ¿Ë·þÁËÆô·¢Ê½ËÑË÷Óöµ½µÄÎÊÌ⣺

ÕâÖÖA*Ëã·¨Óù«Ê½±íʾΪ£º f(n)=g(n)+h(n),
Ò²¾ÍÖ¸´úÕâ¾ä´úÂ룺
priority = new_cost
+ heuristic(goal, next) |
ÆäÖУ¬ f(n) Ö¸µ±Ç°nµãµÄ×Ü´ú¼Û(Ò²¾ÍÊÇpriority£¬×Ü´ú¼ÛÔ½µÍ£¬priorityԽС£¬ÓÅÏȼ¶Ô½¸ß£¬Ô½Ôç±»frontier.get()±éÀúµ½)£¬g(n)
Ö¸new_cost£¬´ÓÆðµãµ½nµãÒÑÖªµÄ´ú¼Û£¬h(n) ÊÇ´Ónµãµ½ÖÕµãËùÐè´ú¼ÛµÄ¹ÀËã
|