簡體   English   中英

找出網格中所有可能路徑的數量,從 (0, 0) 到 (n, n)

[英]Find the number of all possible path in a grid, from (0, 0) to (n, n)

我不知道如何找到網格中所有可能路徑的數量,從 A 點到 B 點。A 點在 (0,0) 上,B 點在 (n,n) 上。 A 可以上下左右移動,不能在訪問點上移動。 當 A 移動時,A(x,y) = (x,y|(0=<x=<n)∩(0=<y=<n))。

我建議用天真的遞歸來解決這個問題。

保留一組您visted的地方。 在故意不是任何特定語言的偽代碼中:

function recursive_call(i, j, visited=none)
    if visited is none then
        visited = set()
    end if
    if i = n and j = n then
        return  1
    else if (i, j) in visited or not in grid then
        return 0
    else
        total = 0
        add (i, j) to visited
        for direction in directions:
            (new_i, new_j) = move(i, j, direction)
            total += recursive_call(new_i, new_j, visited)
        remove (i, j) from visited
        return total
    end if
end function

您可以通過遞歸回溯來解決這個問題,但我認為還有另一種方法更有趣。

如果我們手動計算前幾個案例,我們會發現:

  • 一個 1x1 的正方形有 1 條路徑
  • 一個 2x2 的正方形有 2 條路徑
  • 一個 3x3 的正方形有 12 條路徑

如果我們然后 go 到OEIS(Integer 序列的在線百科全書)並輸入搜索短語“1,2,12 路徑”,第一個結果是A007764 ,其標題為“非交叉路徑的數量(或自回避路徑)連接 n X n 網格的對角”。

了解您正在尋找的 integer 序列可以解鎖重要的數學資源,包括生成序列的源代碼、相關序列和最知名的值。

該序列的已知值為:

1 1
2 2
3 12
4 184
5 8512
6 1262816
7 575780564
8 789360053252
9 3266598486981642
10 41044208702632496804
11 1568758030464750013214100
12 182413291514248049241470885236
13 64528039343270018963357185158482118
14 69450664761521361664274701548907358996488
15 227449714676812739631826459327989863387613323440
16 2266745568862672746374567396713098934866324885408319028
17 68745445609149931587631563132489232824587945968099457285419306
18 6344814611237963971310297540795524400449443986866480693646369387855336
19 1782112840842065129893384946652325275167838065704767655931452474605826692782532
20 1523344971704879993080742810319229690899454255323294555776029866737355060592877569255844
21 3962892199823037560207299517133362502106339705739463771515237113377010682364035706704472064940398
22 31374751050137102720420538137382214513103312193698723653061351991346433379389385793965576992246021316463868
23 755970286667345339661519123315222619353103732072409481167391410479517925792743631234987038883317634987271171404439792
24 55435429355237477009914318489061437930690379970964331332556958646484008407334885544566386924020875711242060085408513482933945720
25 12371712231207064758338744862673570832373041989012943539678727080484951695515930485641394550792153037191858028212512280926600304581386791094
26 8402974857881133471007083745436809127296054293775383549824742623937028497898215256929178577083970960121625602506027316549718402106494049978375604247408
27 17369931586279272931175440421236498900372229588288140604663703720910342413276134762789218193498006107082296223143380491348290026721931129627708738890853908108906396

您可以使用遞歸回溯自己生成前幾個術語:

from typing import Final, List, Set, Tuple

def walk(x: int, y: int, destx: int, desty: int, used: Set[Tuple[int, int]]) -> int:
  """
  Recursive function to calculate the number of self-avoiding walks

  Our strategy here is to build a function that generates self-avoiding walks in
  a depth-first manner using backtracking to avoid duplication and a hash-set to
  avoid overlaps.

  Args:
    n       - How far we are into the walk
    x       - Current x location
    y       - Current y location

  Returns:
    The number of self-avoiding walks of length `n_max`
  """
  # Possible displacement values on a square lattice
  dr_vals: Final[List[Tuple[int, int]]] = [(-1, 0), (1, 0), (0, 1), (0, -1)]

  # Don't walk off the grid
  if x<0 or x == destx:
    return 0
  if y<0 or y == desty:
    return 0
  if x == destx-1 and y==desty-1:
    return 1

  # Make a note that we're now at location (x,y) so it is unavailable
  used.add((x,y))

  # Body of recursion: we will count the walks leading away from (x,y)
  walks = 0

  # Look at all the possible directions we can go from here
  for dr in dr_vals:
    # Determine next coordinates given the displacement
    nx = x + dr[0]
    ny = y + dr[1]
    # Don't visit the neighbouring square twice!
    if (nx, ny) in used:
      continue
    # Visit the neighbouring square and count how many walks it has
    walks += walk(x=nx, y=ny, destx=destx, desty=desty, used=used)

  # We've finished the body of the recursion, we now go back up the stack

  # Since we're going back up the stack we no longer occupy (x,y)
  used.remove((x,y))

  return walks

def main():
  # Make a table of how many self-avoiding walks there are in an n x n square
  # Given the exponential increase the cost of computation and simplicity of this
  # algorithm, this will probably run forever
  for n in range(30):
    used: Set[Tuple[int, int]] = set([(1000, 1000)])
    print(n, walk(x=0, y=0, destx=n, desty=n, used=used))

main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM