1. 程式人生 > >【記錄】批處理實現dfs,bfs,雙向bfs,A*尋路

【記錄】批處理實現dfs,bfs,雙向bfs,A*尋路

:: dfs By blackkitty
:: 演算法描述:深搜
set xx_0=0 && set yy_0=-1
set xx_1=1 && set yy_1=0
set xx_2=0 && set yy_2=1
set xx_3=-1 && set yy_3=0
set x=%current_x% && set y=%current_y%

set flag=0
call:dfs %x% %y% 0
goto:eof

:dfs
:: <x> <y>
if "%1_%2" EQU "%end_x%_%end_y%
" (set flag=1 && goto:eof) set dic_%3=0 :dfs_loop1 set tmp=!dic_%3! set/a dfs=%3+1 set/a nx=%1+!xx_%tmp%! set/a ny=%2+!yy_%tmp%! if !vis_%nx%_%ny%! EQU 0 ( if !%map%_%nx%_%ny%! EQU 1 ( call go %nx% %ny% call:dfs %nx% %ny% %dfs% ) ) if %flag% EQU 1 (goto:eof) set/a dic_%3+=1
if !dic_%3! LSS 4 (goto dfs_loop1) goto:eof
:: dbfs By blackkitty
:: 演算法描述:逆向廣搜
set xx_0=0&&set yy_0=-1
set xx_1=1&&set yy_1=0
set xx_2=0&&set yy_2=1
set xx_3=-1&&set yy_3=0

set l=0
set r=1
set x0=%end_x%
set y0=%end_y%
set nxt_%end_x%_%end_y%=0

:rbfs
set x=!x%l%!
set y=!y%l%!
:: 在地圖上顯示標記(x,y),演示搜尋過程 :: call:mark %x% %y% . set/a l+=1 if "%x%_%y%" EQU "%start_x%_%start_y%" (goto rush) for /l %%i in (0,1,3) do ( set/a nx=x+!xx_%%i! set/a ny=y+!yy_%%i! set/a val=%map%_!nx!_!ny! if "!val!" EQU "1" ( if not defined nxt_!nx!_!ny! ( set nxt_!nx!_!ny!=!x!_!y! set x!r!=!nx! set y!r!=!ny! set/a r+=1 ) ) ) goto rbfs :rush set vv=!nxt_%start_x%_%start_y%! :rush_loop if "%vv%" EQU "0" (goto:eof) call go %vv:_= % set vv=!nxt_%vv%! goto rush_loop :mark :: <x> <y> 在地圖上顯示標記(x,y),用來演示搜尋過程 set/a _x=%1*2+%maze_x% && set/a _y=%2+%maze_y% cc %_x% %_y% && echo.%~3 goto:eof

BFS

:: dbfs By blackkitty
:: 演算法描述:雙向廣搜
set xx_0=0&&set yy_0=-1
set xx_1=1&&set yy_1=0
set xx_2=0&&set yy_2=1
set xx_3=-1&&set yy_3=0

set l=0
set r=2
set x0=%start_x%
set y0=%start_y%
set v%start_x%_%start_y%=pre
set pre_%start_x%_%start_y%=0
set x1=%end_x%
set y1=%end_y%
set v%end_x%_%end_y%=nxt
set nxt_%end_x%_%end_y%=0

:dbfs
set x=!x%l%!
set y=!y%l%!
:: 在地圖上顯示標記(x,y),演示搜尋過程
:: call:mark %x% %y% .
set v=!v%x%_%y%!
set/a l+=1
set/a i=0
:loop
set/a nx=%x%+!xx_%i%!
set/a ny=%y%+!yy_%i%!
if "!%map%_%nx%_%ny%!" EQU "1" (
:: 若臨塊為路
    if "!v%nx%_%ny%!" NEQ "%v%" (
    :: 若臨塊的標記與本塊不同
        if defined v%nx%_%ny% (
            ::找到通路
            if "%v%" EQU "pre" (
                call:rush %x% %y% %nx% %ny%
            ) else (
                call:rush %nx% %ny% %x% %y% 
            )
            goto:eof
        )
    :: 若臨塊的標記與本塊不同,且臨塊無標記
        set %v%_%nx%_%ny%=%x%_%y%
        set x%r%=%nx%&&set y%r%=%ny%&&set v%nx%_%ny%=%v%
        set/a r+=1
    )
)
set/a i+=1&&if "!i!" NEQ "4" (goto loop)
goto dbfs

:rush
set vv=%1_%2
:rvs_loop
if "!pre_%vv%!" EQU "0" (goto rvs_lopp_end)
set nxt_!pre_%vv%!=%vv%
set vv=!pre_%vv%!
goto rvs_loop
:rvs_lopp_end
set nxt_%1_%2=%3_%4
set vv=!nxt_%start_x%_%start_y%!
:rush_loop
if "%vv%" EQU "0" (goto:eof)
call go %vv:_= %
set vv=!nxt_%vv%!
goto rush_loop

:mark
:: <x> <y> 在地圖上顯示標記(x,y),用來演示搜尋過程
set/a _x=%1*2+%maze_x% && set/a _y=%2+%maze_y%
cc %_x% %_y% && echo.%~3
goto:eof

DBFS

:: astar By blackkitty
:: 演算法描述:逆向啟發式A*
set xx_0=0&&set yy_0=-1
set xx_1=1&&set yy_1=0
set xx_2=0&&set yy_2=1
set xx_3=-1&&set yy_3=0

set new=1
set x0=%end_x%
set y0=%end_y%
set nxt_%end_x%_%end_y%=0
set gn0=0
set fn0=0
set list=n0
set/a maxfn=!%map%_width!*!%map%_height!

:astar
set vv=_
set minfn=%maxfn%
:: 從列表選取fn最小的位置
for %%k in (%list%) do (
    if !f%%k! LSS !minfn! (
        set minfn=!f%%k!
        set vv=%%k
    )
)
:: 從列表中刪除這個位置
set list=!list:%vv%=!
set vv=%vv:~1%
set x=!x%vv%!
set y=!y%vv%!

:: 在地圖上顯示標記(x,y),演示搜尋過程
call:mark %x% %y% .

if "%x%_%y%" EQU "%start_x%_%start_y%" (goto rush)
for /l %%i in (0,1,3) do (
    set/a nx=x+!xx_%%i!
    set/a ny=y+!yy_%%i!
    set/a val=%map%_!nx!_!ny!
    if "!val!" EQU "1" (
        if not defined nxt_!nx!_!ny! (
            set nxt_!nx!_!ny!=!x!_!y!
            :: 加入列表
            set list=!list! n!new!
            :: 計算gn
            set/a gn!new!=!gn%vv%!+1
            :: 計算fn儲存至fn!new!
            call:fn !nx! !ny! gn!new! fn!new!
            set x!new!=!nx!
            set y!new!=!ny!
            set/a new+=1
        )
    )
)
goto astar

:rush
pause>nul
set vv=!nxt_%start_x%_%start_y%!
:rush_loop
if "%vv%" EQU "0" (goto:eof)
call go %vv:_= %
set vv=!nxt_%vv%!
goto rush_loop


:fn
:: <x> <y> [gn] [ret] 起點到x,y的估計代價(fn = gn + hn)
:: gn 終點到(x,y)的實際代價
:: hn 起點到(x,y)的估計代價,估值為起點到(x,y)的曼哈頓距離
set/a tmp=%1-%start_x%
if %tmp% LSS 0 (set/a tmp=-tmp)
set %4=%tmp%
set/a tmp=%2-%start_y%
if %tmp% LSS 0 (set/a tmp=-tmp)
set/a %4=!%4!+%tmp%+!%3!
goto:eof

:mark
:: <x> <y> 在地圖上顯示標記(x,y),用來演示搜尋過程
set/a _x=%1*2+%maze_x% && set/a _y=%2+%maze_y%
cc %_x% %_y% && echo.%~3
goto:eof

astar