楼主: 〇〇

[精华] ACM题(#2634 Collecting Stones)

[复制链接]
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
71#
 楼主| 发表于 2011-4-12 16:20 | 只看该作者
原帖由 rollingpig 于 2011-4-12 16:17 发表
MAX(TST),MIN(TST)
1948,328

pathstr?

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
72#
 楼主| 发表于 2011-4-12 16:26 | 只看该作者
SQL> exec :m:=2000
已用时间:  00: 00: 00.00
SQL> @c:\downloads\rp1

N
-
N
已用时间:  00: 00: 00.12
把/*+ 改为/*-
SQL> @c:\downloads\rp1

N
-
N
已用时间:  00: 00: 42.30

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
73#
发表于 2011-4-12 16:28 | 只看该作者
讨论得很激烈,请继续,并请详解思路

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
74#
发表于 2011-4-12 17:01 | 只看该作者
呵呵,思路很简单
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以内。


  1. drop table grid  ;
  2. create table grid(x,y,n,s,st) as
  3. select x,y,x*8+y,chr(x*8+y),round(dbms_random.value(10,100)) from
  4. (select rownum-1 as x from dual connect by rownum <= 8),
  5. (select rownum as y from dual connect by rownum <= 8)  ;

  6. WITH                                                                                                  
  7. p1(srcblock,destblock,tst,pathstr) AS (
  8.   SELECT  /*+ materialize no_merge */ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  9.   from grid a , grid b
  10.    where
  11.    a.n=1    -- Start with first block
  12.    and b.n in (a.n + 8)
  13.   UNION ALL
  14.   SELECT /*+ materialize */
  15.   a.srcblock,b.n,
  16.   a.tst + b.st,--st
  17.   pathstr||b.s
  18.   FROM  p1 a , (select * from grid where y in (1)) b
  19.   WHERE         b.n in (
  20.   a.destblock + 8
  21.   ) and b.n!=1
  22.   AND a.tst + b.st <=:M
  23.   and instr(pathstr,s)=0
  24. ),
  25. p2(srcblock,destblock,tst,pathstr) AS (
  26.   SELECT  /*+ materialize no_merge */ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  27.   from grid a , grid b
  28.    where  a.y in (2)
  29.    and b.n in (a.n + 8, a.n -8 )
  30.   UNION ALL
  31.   SELECT
  32.   a.srcblock,b.n,
  33.   a.tst + b.st,--st
  34.   pathstr||b.s
  35.   FROM  p2 a , (select * from grid where y in (2)) b
  36.   WHERE         b.n in (
  37.   a.destblock + 8  , a.destblock - 8
  38.   )
  39.   AND a.tst + b.st <=:M
  40.   and instr(pathstr,s)=0
  41. ),
  42. p3(srcblock,destblock,tst,pathstr) AS (
  43.   SELECT  /*+ materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  44.   from grid a , grid b
  45.    where  a.y in (3)
  46.    and b.n in (a.n + 8, a.n -8 )
  47.   UNION ALL
  48.   SELECT
  49.   a.srcblock,b.n,                     
  50.   a.tst + b.st,--st
  51.   pathstr||b.s
  52.   FROM  p3 a , (select * from grid where y in (3)) b
  53.   WHERE         b.n in (
  54.   a.destblock + 8  , a.destblock - 8
  55.   )
  56.   AND a.tst + b.st <=:M
  57.   and instr(pathstr,s)=0
  58. ),
  59. p4(srcblock,destblock,tst,pathstr) AS (
  60.   SELECT  /*+ materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  61.   from grid a , grid b
  62.    where  a.y in (4)
  63.    and b.n in (a.n + 8, a.n -8 )
  64.   UNION ALL
  65.   SELECT
  66.   a.srcblock,b.n,
  67.   a.tst + b.st,--st
  68.   pathstr||b.s
  69.   FROM  p4 a , (select * from grid where y in (4)) b
  70.   WHERE         b.n in (
  71.   a.destblock + 8  , a.destblock - 8
  72.   )
  73.   AND a.tst + b.st <=:M
  74.   and instr(pathstr,s)=0
  75. ),
  76. p5(srcblock,destblock,tst,pathstr) AS (
  77.   SELECT  /*+ materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  78.   from grid a , grid b
  79.    where  a.y in (5)
  80.    and b.n in (a.n + 8, a.n -8 )
  81.   UNION ALL
  82.   SELECT
  83.   a.srcblock,b.n,
  84.   a.tst + b.st,--st
  85.   pathstr||b.s
  86.   FROM  p5 a , (select * from grid where y in (5)) b
  87.   WHERE         b.n in (
  88.   a.destblock + 8  , a.destblock - 8
  89.   )
  90.   AND a.tst + b.st <=:M
  91.   and instr(pathstr,s)=0
  92. ),
  93. p6(srcblock,destblock,tst,pathstr) AS (
  94.   SELECT  /*+materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  95.   from grid a , grid b
  96.    where  a.y in (6)
  97.    and b.n in (a.n + 8, a.n -8 )
  98.   UNION ALL
  99.   SELECT
  100.   a.srcblock,b.n,
  101.   a.tst + b.st,--st
  102.   pathstr||b.s
  103.   FROM  p6 a , (select * from grid where y in (6)) b
  104.   WHERE         b.n in (
  105.   a.destblock + 8  , a.destblock - 8
  106.   )
  107.   AND a.tst + b.st <=:M
  108.   and instr(pathstr,s)=0
  109. ),
  110. p7(srcblock,destblock,tst,pathstr) AS (
  111.   SELECT  /*+materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  112.   from grid a , grid b
  113.    where  a.y in (7)
  114.    and b.n in (a.n + 8, a.n -8 )
  115.   UNION ALL
  116.   SELECT
  117.   a.srcblock,b.n,
  118.   a.tst + b.st,--st
  119.   pathstr||b.s
  120.   FROM  p7 a , (select * from grid where y in (7)) b
  121.   WHERE         b.n in (
  122.   a.destblock + 8  , a.destblock - 8
  123.   )
  124.   AND a.tst + b.st <=:M
  125.   and instr(pathstr,s)=0
  126. ),
  127. p8(srcblock,destblock,tst,pathstr) AS (
  128.   SELECT  /*+materialize no_merge*/ a.n,b.n,a.st+b.st,cast(a.s||b.s as varchar2(100))
  129.   from grid a , grid b
  130.    where a.n=64
  131.    and b.n in (a.n -8 )
  132.   UNION ALL
  133.   SELECT
  134.   a.srcblock,b.n,
  135.   a.tst + b.st,--st
  136.   pathstr||b.s
  137.   FROM  p8 a , (select * from grid where y in (8)) b
  138.   WHERE         b.n in ( a.destblock - 8 )
  139.   AND a.tst + b.st <=:M
  140.   and instr(pathstr,s)=0
  141. ),
  142. p12 as (
  143. select /*+ materialize no_merge use_concat ordered use_hash(a b)   */ distinct b.destblock,a.tst+b.tst  tst
  144. from p1 a,p2 b
  145. where
  146.   b.srcblock in (
  147.   a.destblock + 1 ,
  148.   a.destblock - 7 ,
  149.   a.destblock + 9
  150. )
  151.   AND a.tst + b.tst <:M
  152. ),
  153. p13 as (
  154. select /*+ materialize no_merge ordered use_concat  use_hash(a b)   */ distinct b.destblock,a.tst+b.tst  tst
  155. from  p3 b , (
  156. select /*+no_merge(p12) */ tst, destblock+1 as destblock from p12
  157. union all
  158. select /*+no_merge(p12) */  tst, destblock+9 as destblock from p12
  159. union all
  160. select  /*+no_merge(p12) */ tst, destblock-7 as destblock from p12
  161. ) a   
  162. where
  163.   b.srcblock =  a.destblock
  164.   AND a.tst + b.tst <:M
  165. ),
  166. p14 as (
  167. select /*+ materialize no_merge ordered use_concat  use_hash(a b)  no_merge(a) */ distinct b.destblock,a.tst+b.tst  tst
  168. from p4 b,  
  169. (
  170. select /*+no_merge(p13) */ tst, destblock+1 as destblock from p13
  171. union all
  172. select /*+no_merge(p13) */  tst, destblock+9 as destblock from p13
  173. union all
  174. select  /*+no_merge(p13) */ tst, destblock-7 as destblock from p13
  175. ) a   
  176. where
  177.   b.srcblock =  a.destblock
  178.   AND a.tst + b.tst <:M
  179. ) ,
  180. p87 as (
  181. select /*+ materialize no_merge use_concat ordered use_hash(a b)   */ distinct b.destblock,a.tst+b.tst  tst
  182. from p8 a,p7 b
  183. where
  184.   b.srcblock in (
  185.   a.destblock - 1 ,
  186.   a.destblock + 7 ,
  187.   a.destblock - 9
  188. )
  189.   AND a.tst + b.tst <:M
  190. ),
  191. p86 as (
  192. select /*+ materialize no_merge ordered use_concat  use_hash(a b)   */ distinct b.destblock,a.tst+b.tst  tst
  193. from  p6 b ,
  194. ( select /*+no_merge(p87) */ tst, destblock-1 as destblock from p87
  195. union all
  196. select /*+no_merge(p87) */  tst, destblock-9 as destblock from p87
  197. union all
  198. select  /*+no_merge(p87) */ tst, destblock+7 as destblock from p87) a
  199. where
  200.   b.srcblock =a.destblock
  201.   AND a.tst + b.tst <:M
  202. ),
  203. p85 as (
  204. select /*+ materialize no_merge ordered use_concat  use_hash(a b)  */ distinct b.destblock,a.tst+b.tst  tst
  205. from  p5 b,
  206. ( select /*+no_merge(p87) */ tst, destblock-1 as destblock from p86
  207. union all
  208. select /*+no_merge(p87) */  tst, destblock-9 as destblock from p86
  209. union all
  210. select  /*+no_merge(p87) */ tst, destblock+7 as destblock from p86) a
  211. where
  212.   b.srcblock =a.destblock
  213.   AND a.tst + b.tst <:M
  214. ),
  215. p18 as (
  216. select /*+use_hash(a b)  */'Y' f,a.tst+b.tst tst from p14 a,p85 b
  217. where
  218.   b.destblock in (
  219.   a.destblock + 1 ,
  220.   a.destblock - 7 ,
  221.   a.destblock + 9
  222. ) and  b.tst = :M - a.tst and rownum = 1
  223. )
  224. select nvl(max(f),'N') from p18  

复制代码

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
75#
 楼主| 发表于 2011-4-12 17:01 | 只看该作者
我偷偷用了滚珠的hint,大数也变快了
SQL> exec :m:=500
已用时间:  00: 00: 00.00
SQL> @c:\downloads\rpo

N
-
Y
已用时间:  00: 00: 00.13
SQL> @c:\downloads\26345rp

T.PATH||'*'||T2.PATH
-----------------------------------------------------------------------------------------------------------------------------
,01,09,17,25,33,34,26,18,10,19,27,35,44*37,46,55,64,
已用时间:  00: 00: 00.43
SQL> exec :m:=900
已用时间:  00: 00: 00.00
SQL> @c:\downloads\26345rp

T.PATH||'*'||T2.PATH
-----------------------------------------------------------------------------------------------------------------------------
,01,09,17,25,33,41,49,57,58,50,42,34,26,35,43,51,59,52*45,54,55,64,
已用时间:  00: 00: 00.43
SQL> exec :m:=1100
已用时间:  00: 00: 00.00
SQL> @c:\downloads\26345rp

T.PATH||'*'||T2.PATH
-----------------------------------------------------------------------------------------------------------------------------
,01,09,17,25,33,41,49,57,58,50,42,34,26,18,11,19,27,35,43,51,59,60*53,62,54,47,55,64,
已用时间:  00: 00: 00.50
SQL> exec :m:=1500
已用时间:  00: 00: 00.00
SQL> @c:\downloads\26345rp

T.PATH||'*'||T2.PATH
-----------------------------------------------------------------------------------------------------------------------------
,01,09,17,25,33,41,49,57,58,50,42,34,26,18,11,19,27,35,43,51,59,52*45,38,46,54,62,63,55,47,39,31,23,32,40,48,56,64,
已用时间:  00: 00: 03.06
SQL> exec :m:=1912
已用时间:  00: 00: 00.00
SQL> @c:\downloads\26345rp
已用时间:  00: 00: 11.21
SQL> exec :m:=1948
已用时间:  00: 00: 00.00
SQL> @c:\downloads\26345rp
已用时间:  00: 00: 11.08

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
76#
 楼主| 发表于 2011-4-12 17:04 | 只看该作者
但是后边的几个算不出来,不知错在哪里


  1. WITH d AS (
  2.   SELECT to_char(ROWNUM,'fm09') id
  3.         ,CEIL(ROWNUM/8) r
  4.         ,MOD(ROWNUM-1,8)+1 c
  5.         ,ROWNUM val
  6.     FROM DUAL
  7.    CONNECT BY ROWNUM<=64
  8.   )
  9. ,t(r,c,val,total,path) AS (
  10.   SELECT r,c,val,val,','||CAST(id AS VARCHAR2(4000)) FROM d WHERE r=1 AND c=1
  11.   UNION ALL
  12.   SELECT d.r,d.c,d.val,d.val+t.total,t.path||','||d.id
  13.     FROM t, d
  14.    WHERE INSTR(t.path||',',','||d.id||',')=0
  15.          AND (d.r,d.c) IN ((t.r-1,t.c),(t.r+1,t.c),(t.r,t.c+1),(t.r-1,t.c+1),(t.r+1,t.c+1))
  16.          AND d.val+t.total<:M
  17.          and t.c<4
  18.   )
  19. ,t2(r,c,val,total,path) AS (
  20.   SELECT r,c,val,val,CAST(id AS VARCHAR2(4000))||',' FROM d WHERE r=8 AND c=8
  21.   UNION ALL
  22.   SELECT d.r,d.c,d.val,d.val+t.total,d.id||','||t.path
  23.     FROM t2 t, d
  24.    WHERE INSTR(t.path||',',','||d.id||',')=0
  25.          AND (d.r,d.c) IN ((t.r+1,t.c),(t.r-1,t.c),(t.r,t.c-1),(t.r+1,t.c-1),(t.r-1,t.c-1))
  26.          AND d.val+t.total<:M
  27.          and t.c>5
  28.   )
  29. SELECT /*+ materialize no_merge use_concat ordered use_hash(t t2)   */t.path||'*'||t2.path FROM t,t2
  30. WHERE (t.r=t2.r or t.r=t2.r-1 or  t.r=t2.r+1)AND t.c=4 and t2.c=4+1
  31. AND t.total+t2.total=:M and rownum=1;


复制代码

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
77#
发表于 2011-4-12 17:24 | 只看该作者
原帖由 〇〇 于 2011-4-12 16:20 发表

pathstr?


0+1+9+17+25+33+41+49+57+58+50+59+51+43+35+27+19+11+3+4+12+20+28+36+44+52+60
0+61+53+45+37+29+21+13+5+6+14+22+30+38+46+54+62+63+55+47+39+31+23+15+7+8+16+24+32+40+48+56+64

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
78#
发表于 2011-4-12 17:25 | 只看该作者
AND t.total+t2.total=:M and rownum=1;
==>

AND t.total=:M- t2.total and rownum=1;

就成hash了


原帖由 〇〇 于 2011-4-12 17:04 发表
但是后边的几个算不出来,不知错在哪里


WITH d AS (
  SELECT to_char(ROWNUM,'fm09') id
        ,CEIL(ROWNUM/8) r
        ,MOD(ROWNUM-1,8)+1 c
        ,ROWNUM val
    FROM DUAL
   CONNECT BY ROWNUM

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
79#
发表于 2011-4-12 17:30 | 只看该作者
SELECT /*+ materialize no_merge use_concat ordered use_hash(t t2)   */t.path||'*'||t2.path FROM t,t2


==

SELECT /*+ ordered use_hash(t t2)   */t.path||'*'||t2.path FROM t,t2
去掉use_concat, 基本一秒没问题

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
80#
发表于 2011-4-12 17:33 | 只看该作者
and t.c<4
==>
and t.c<=4


and t.c>5
==>
and t.c>=4

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表