|
呵呵,思路很简单
1. 每个列先单独找出列内的路径及石头数
2. 分别从1和64出发,其中64反方向走
1列并上2列并上3列并上4列,中间用total stone <:M过滤
8列并上7列并上6列并上5列,中间用total stone <:M过滤
最后在中间相遇。
下面的code稍微在原表添加了几个字段,避免后期运算
另外,从执行计划看,不知道为什么,几个cascade with 总是不能实体化,导致重复运算(3x),所以性能还是有提升空间。
再考虑到SQL引擎本身的开销,估计用类似算法写成C/C++, 应该可以到100ms以内。
- drop table grid ;
- create table grid(x,y,n,s,st) as
- select x,y,x*8+y,chr(x*8+y),round(dbms_random.value(10,100)) from
- (select rownum-1 as x from dual connect by rownum <= 8),
- (select rownum as y from dual connect by rownum <= 8) ;
- WITH
- p1(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+ materialize no_merge */ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where
- a.n=1 -- Start with first block
- and b.n in (a.n + 8)
- UNION ALL
- SELECT /*+ materialize */
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p1 a , (select * from grid where y in (1)) b
- WHERE b.n in (
- a.destblock + 8
- ) and b.n!=1
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p2(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+ materialize no_merge */ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.y in (2)
- and b.n in (a.n + 8, a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p2 a , (select * from grid where y in (2)) b
- WHERE b.n in (
- a.destblock + 8 , a.destblock - 8
- )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p3(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+ materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.y in (3)
- and b.n in (a.n + 8, a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p3 a , (select * from grid where y in (3)) b
- WHERE b.n in (
- a.destblock + 8 , a.destblock - 8
- )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p4(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+ materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.y in (4)
- and b.n in (a.n + 8, a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p4 a , (select * from grid where y in (4)) b
- WHERE b.n in (
- a.destblock + 8 , a.destblock - 8
- )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p5(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+ materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.y in (5)
- and b.n in (a.n + 8, a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p5 a , (select * from grid where y in (5)) b
- WHERE b.n in (
- a.destblock + 8 , a.destblock - 8
- )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p6(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.y in (6)
- and b.n in (a.n + 8, a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p6 a , (select * from grid where y in (6)) b
- WHERE b.n in (
- a.destblock + 8 , a.destblock - 8
- )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p7(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.y in (7)
- and b.n in (a.n + 8, a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p7 a , (select * from grid where y in (7)) b
- WHERE b.n in (
- a.destblock + 8 , a.destblock - 8
- )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p8(srcblock,destblock,tst,pathstr) AS (
- SELECT /*+materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
- from grid a , grid b
- where a.n=64
- and b.n in (a.n -8 )
- UNION ALL
- SELECT
- a.srcblock,b.n,
- a.tst + b.st,--st
- pathstr||b.s
- FROM p8 a , (select * from grid where y in (8)) b
- WHERE b.n in ( a.destblock - 8 )
- AND a.tst + b.st <=:M
- and instr(pathstr,s)=0
- ),
- p12 as (
- select /*+ materialize no_merge use_concat ordered use_hash(a b) */ distinct b.destblock,a.tst+b.tst tst
- from p1 a,p2 b
- where
- b.srcblock in (
- a.destblock + 1 ,
- a.destblock - 7 ,
- a.destblock + 9
- )
- AND a.tst + b.tst <:M
- ),
- p13 as (
- select /*+ materialize no_merge ordered use_concat use_hash(a b) */ distinct b.destblock,a.tst+b.tst tst
- from p3 b , (
- select /*+no_merge(p12) */ tst, destblock+1 as destblock from p12
- union all
- select /*+no_merge(p12) */ tst, destblock+9 as destblock from p12
- union all
- select /*+no_merge(p12) */ tst, destblock-7 as destblock from p12
- ) a
- where
- b.srcblock = a.destblock
- AND a.tst + b.tst <:M
- ),
- p14 as (
- select /*+ materialize no_merge ordered use_concat use_hash(a b) no_merge(a) */ distinct b.destblock,a.tst+b.tst tst
- from p4 b,
- (
- select /*+no_merge(p13) */ tst, destblock+1 as destblock from p13
- union all
- select /*+no_merge(p13) */ tst, destblock+9 as destblock from p13
- union all
- select /*+no_merge(p13) */ tst, destblock-7 as destblock from p13
- ) a
- where
- b.srcblock = a.destblock
- AND a.tst + b.tst <:M
- ) ,
- p87 as (
- select /*+ materialize no_merge use_concat ordered use_hash(a b) */ distinct b.destblock,a.tst+b.tst tst
- from p8 a,p7 b
- where
- b.srcblock in (
- a.destblock - 1 ,
- a.destblock + 7 ,
- a.destblock - 9
- )
- AND a.tst + b.tst <:M
- ),
- p86 as (
- select /*+ materialize no_merge ordered use_concat use_hash(a b) */ distinct b.destblock,a.tst+b.tst tst
- from p6 b ,
- ( select /*+no_merge(p87) */ tst, destblock-1 as destblock from p87
- union all
- select /*+no_merge(p87) */ tst, destblock-9 as destblock from p87
- union all
- select /*+no_merge(p87) */ tst, destblock+7 as destblock from p87) a
- where
- b.srcblock =a.destblock
- AND a.tst + b.tst <:M
- ),
- p85 as (
- select /*+ materialize no_merge ordered use_concat use_hash(a b) */ distinct b.destblock,a.tst+b.tst tst
- from p5 b,
- ( select /*+no_merge(p87) */ tst, destblock-1 as destblock from p86
- union all
- select /*+no_merge(p87) */ tst, destblock-9 as destblock from p86
- union all
- select /*+no_merge(p87) */ tst, destblock+7 as destblock from p86) a
- where
- b.srcblock =a.destblock
- AND a.tst + b.tst <:M
- ),
- p18 as (
- select /*+use_hash(a b) */'Y' f,a.tst+b.tst tst from p14 a,p85 b
- where
- b.destblock in (
- a.destblock + 1 ,
- a.destblock - 7 ,
- a.destblock + 9
- ) and b.tst = :M - a.tst and rownum = 1
- )
- select nvl(max(f),'N') from p18
复制代码 |
|