找到迷宫中的最短路径,SQL

时间:2017-11-04 23:31:50

标签: sql oracle maze

如何找到(例如)此迷宫中的最短路径(在明确的SQL上,不使用PL / SQL函数):

起点:'s',终点:'e'

'00   000  e000000'  
'         0       '
'0000 000 0 00000 '
'   0   0   0     '
's0 000 000 00000 '
' 0               '

结果,应该有这样的东西

'00   000  e000000'  
'         0-      '
'0000 000 0-00000 '
'---0   0  -0     '
's0-000 000-00000 '
' 0---------      '

我不是在等待SQL代码中的现成解决方案,但我不知道它是如何在SQL中解决的。谁能知道任何算法?目标数据库Oracle。

2 个答案:

答案 0 :(得分:1)

既然你在征求意见:

  1. 在“普通”SQL SELECT语句中无法表达可达性查询,除非......
  2. 递归公用表表达式(WITH子句)可以使SQL SELECT语句Turing-complete。

答案 1 :(得分:1)

有两种方法

  1. 使用递归子查询分解的暴力。
  2. 李算法使用模型子句+迭代。 https://en.wikipedia.org/wiki/Lee_algorithm
  3. <强>更新。快速演示第一种方法。

    column str format a30
    with t(y, str) as
    (         select 1, '00   000  e000000' from dual
    union all select 2, '         0       ' from dual
    union all select 3, '0000 000 0 00000 ' from dual
    union all select 4, '   0   0   0     ' from dual
    union all select 5, 's0 000 000 00000 ' from dual
    union all select 6, ' 0               ' from dual)
    , matrix as
    (select x, y, str, substr(str, x, 1) z, rownum id
    from t
    cross join (select rownum x from dual connect by level <= 17))
    , rec(x,y,z,id_list) as
    (select x, y, z, cast(id as varchar2(4000)) from matrix where z = 's'
    union all
    select m.x, m.y, m.z, r.id_list || '|' || m.id
    from matrix m
    join rec r on (r.x + 1 = m.x and r.y = m.y
               or r.x - 1 = m.x and r.y = m.y
               or r.x = m.x and r.y + 1 = m.y
               or r.x = m.x and r.y - 1 = m.y)
              and instr('|' || r.id_list || '|', '|' || m.id || '|') = 0
              and m.z != '0'
              and r.z = any ('s', ' ')
    )
    , route as
    (select regexp_substr(x, '\d+', 1, rownum) mark
    from
    (select max(id_list) keep 
            (dense_rank first order by regexp_count(id_list,'|')) x
    from rec
    where z = 'e')
    connect by level <= regexp_count(x,'|'))
    select y, listagg(decode(z, ' ', nvl2(mark, '=', z), z))
              within group (order by x) str
    from matrix
    left join route on id = mark
    group by y
    order by y;
    
             Y STR                           
    ---------- ------------------------------
             1 00   000  e000000             
             2          0=                   
             3 0000 000 0=00000              
             4 ===0   0  =0                  
             5 s0=000 000=00000              
             6  0=========                   
    
    6 rows selected.
    

    模型解决方案效率更高,但SQL并不是解决此特定任务的最佳方法。