楼主: 〇〇

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

[复制链接]
论坛徽章:
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
51#
发表于 2011-4-12 13:31 | 只看该作者
勉强在3秒内算出374.


  1. var m number
  2. exec :m:=374

  3. WITH
  4. routes2way1(srcblock,destblock,stones) AS( -- 把grid里的blocknumber改为相应的blockud,同时,构造双向通道表。
  5. select (BLOCKNUMBER-8),(BLOCKNUMBER),stones from grid where mod(BLOCKNUMBER-8,8)<=4 and  mod(BLOCKNUMBER+8,8)>0 and BLOCKNUMBER-8>0   -- Move down
  6. union all
  7. select (BLOCKNUMBER+8),(BLOCKNUMBER),stones from grid where mod(BLOCKNUMBER+8,8)<=4 and  mod(BLOCKNUMBER+8,8)>0 and (BLOCKNUMBER+8)<=64 and BLOCKNUMBER!=1  --Move up
  8. union all
  9. select (BLOCKNUMBER-1),(BLOCKNUMBER),stones from grid where mod(BLOCKNUMBER-1,8)<4 and mod(blocknumber,8) !=1--Move right     
  10. union all
  11. select (BLOCKNUMBER-9),(BLOCKNUMBER),stones from grid where mod(blocknumber-1,8)<4 and mod(blocknumber,8)!=1 and BLOCKNUMBER-9>0  --Move down right
  12. union all
  13. select (BLOCKNUMBER+7),(BLOCKNUMBER),stones from grid where mod(blocknumber+7,8)<4 and mod(blocknumber,8)!=1 and BLOCKNUMBER+7<=64  --Move down right
  14. ) ,
  15. routes2way2(srcblock,destblock,stones) AS( -- 把grid里的blocknumber改为相应的blockud,同时,构造双向通道表。
  16. select (BLOCKNUMBER+8),(BLOCKNUMBER),stones from grid where (mod(BLOCKNUMBER+8,8)>4 or mod(BLOCKNUMBER+8,8)=0) and BLOCKNUMBER+8<=64 -- Move up
  17. union all
  18. select (BLOCKNUMBER-8),(BLOCKNUMBER),stones from grid where (mod(BLOCKNUMBER-8,8)>4 or mod(BLOCKNUMBER-8,8)=0) and (BLOCKNUMBER-8)>0 and BLOCKNUMBER!=64--Move down
  19. union all
  20. select (BLOCKNUMBER+1),(BLOCKNUMBER),stones from grid where (mod(BLOCKNUMBER+1,8)>5 or mod(BLOCKNUMBER+1,8)=0) --Move left     
  21. union all
  22. select (BLOCKNUMBER-7),(BLOCKNUMBER),stones from grid where (mod(BLOCKNUMBER-7,8)>5 or mod(BLOCKNUMBER-7,8)=0) and BLOCKNUMBER-7>0  --Move down left
  23. union all
  24. select (BLOCKNUMBER+9),(BLOCKNUMBER),stones from grid where (mod(BLOCKNUMBER+9,8)>5 or mod(BLOCKNUMBER+9,8)=0) and BLOCKNUMBER+9<=64  --Move up right
  25. ) ,
  26. pathprobe1 (levelN,srcblock,destblock,totalstones) AS ( --先探测3级内的路径
  27.   SELECT  /*+materilize */ 1, srcblock,destblock,routes2way1.stones+grid.stones
  28.   from routes2way1 , grid
  29.    where srcblock =  1  and grid.blocknumber=1    -- Start with first block
  30.   UNION ALL
  31.   SELECT        levelN+1,--递归层数
  32.   a.srcblock,b.destblock,--出发、到达block
  33.   a.totalstones + b.stones--stones
  34.   FROM  pathprobe1 a , routes2way1 b
  35.   WHERE        a.destblock = b.srcblock --join
  36.   AND a.totalstones + b.stones <=:M
  37. ) CYCLE destblock SET cycle_flag TO 'Y' DEFAULT 'N'
  38. ,
  39. path1 as
  40. (
  41. select  destblock,totalstones
  42. from pathprobe1
  43. where srcblock=1 and mod(destblock,8)=4
  44. and  cycle_flag='N'
  45. )
  46. ,
  47. pathprobe2 (levelN,srcblock,destblock,totalstones) AS ( --先探测3级内的路径
  48.   SELECT  /*+materilize */ 1, srcblock,destblock,routes2way2.stones+grid.stones
  49.   from routes2way2 , grid
  50.    where srcblock =  64  and grid.blocknumber=64    -- Start with first block
  51.   UNION ALL
  52.   SELECT        levelN+1,--递归层数
  53.   a.srcblock,b.destblock,--出发、到达block
  54.   a.totalstones + b.stones--stones
  55.   FROM  pathprobe2 a , routes2way2 b
  56.   WHERE        a.destblock = b.srcblock --join
  57.   AND a.totalstones + b.stones <=:M
  58. ),
  59. path2 as (
  60. select destblock,totalstones from pathprobe2
  61. where  srcblock=64 and mod(destblock,8)=5
  62. )  select /*+use_hash(p1 p2)*/ * from  
  63. path1 p1  , path2  p2
  64. where
  65. (
  66. p1.destblock+1 = p2.destblock  or  --Right
  67. p1.destblock+9 = p2.destblock  or --Down right
  68. p1.destblock-7 = p2.destblock -- Up rigth
  69.   )  and  p1.totalstones = :M - p2.totalstones
  70.   and rownum = 1

复制代码

使用道具 举报

回复
论坛徽章:
2
2011新春纪念徽章
日期:2011-01-04 10:38:212011新春纪念徽章
日期:2011-02-18 11:43:33
52#
发表于 2011-4-12 13:36 | 只看该作者
嗯 确认下

1 根据题意,那么左上和右下两个石头是必选的了?

2 如果有多个解,需要输出所有的么,还是需要输出全部?

使用道具 举报

回复
论坛徽章:
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
53#
 楼主| 发表于 2011-4-12 13:41 | 只看该作者
SQL> exec :m:=374
已用时间:  00: 00: 00.00
SQL> @c:\downloads\26345

T.PATH||'*'||T2.PATH
----------------------------------------
,01,02,03,04*13,22,30,38,46,47,48,56,64,
已用时间:  00: 00: 00.07

使用道具 举报

回复
论坛徽章:
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
54#
 楼主| 发表于 2011-4-12 13:42 | 只看该作者
题意是只要输出yes no但为了好验证还是要输出1个,如果有

使用道具 举报

回复
论坛徽章:
8
玉兔
日期:2015-11-16 10:18:00铁扇公主
日期:2015-10-27 21:47:42九尾狐狸
日期:2015-12-11 22:31:15
55#
发表于 2011-4-12 13:52 | 只看该作者
with
d(n) as (select 0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7),
cost(i, j, v) as (select d1.n, d2.n, d1.n * 8 + d2.n + 1 from d d1, d d2),
direction(i, j) as
(
        select 1, 1 union
        select 1, 0 union
        select 1, -1 union
        select 0, 1 union
        select 0, -1),
path14(i, j, v, s) as
(
        select 0, 0, v,
                cast('x' as char(64)) s from cost where i = 0 and j = 0
        union all
        select p.i + d.i, p.j + d.j, p.v + c.v,
                cast(stuff(p.s, 8 * (p.i + d.i) + p.j + d.j + 1, 1, 'x') as char(64)) s
        from path14 p, direction d, cost c
        where p.i + d.i >= 0 and p.i + d.i < 4 -- 在网格内
                and p.j + d.j >= 0 and p.j + d.j < 8
                and substring(p.s, 8 * (p.i + d.i) + p.j + d.j + 1, 1) <> 'x' -- 没访问过
                and p.i + d.i = c.i and p.j + d.j = c.j -- 取得费用
),
path85(i, j, v, s) as
(
        select 7, 7, v,
                cast(stuff(space(64), 8 * 7 + 7 + 1, 1, 'x') as char(64)) s
        from cost where i = 7 and j = 7
        union all
        select p.i - d.i, p.j - d.j, p.v + c.v,
                cast(stuff(p.s, 8 * (p.i - d.i) + p.j - d.j + 1, 1, 'x') as char(64)) s
        from path85 p, direction d, cost c
        where p.i - d.i >= 0 and p.i - d.i >= 4 -- 在网格内
                and p.j - d.j >= 0 and p.j - d.j < 8
                and substring(p.s, 8 * (p.i - d.i) + p.j - d.j + 1, 1) <> 'x' -- 没访问过
                and p.i - d.i = c.i and p.j - d.j = c.j -- 取得费用
),
pa(j, v) as (select j,v from path14 where i=3),
pb(j, v) as (select j,v from path85 where i=4)
select top 1 * from pa, pb
where
        (pa.j = pb.j or pa.j + 1 = pb.j or pa.j - 1 = pb.j)
        and pa.v + pb.v = 374 -- 取值

使用道具 举报

回复
论坛徽章:
8
玉兔
日期:2015-11-16 10:18:00铁扇公主
日期:2015-10-27 21:47:42九尾狐狸
日期:2015-12-11 22:31:15
56#
发表于 2011-4-12 13:54 | 只看该作者
pa, pb 基本上2秒就出来了,就是最后连接慢,这个大家可以想想办法,有路径的时候是很快的,但是没路径......

第5步其实用 C很容易做

使用道具 举报

回复
论坛徽章:
8
玉兔
日期:2015-11-16 10:18:00铁扇公主
日期:2015-10-27 21:47:42九尾狐狸
日期:2015-12-11 22:31:15
57#
发表于 2011-4-12 13:54 | 只看该作者
374在我这里只要19ms

使用道具 举报

回复
论坛徽章:
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
58#
 楼主| 发表于 2011-4-12 14:50 | 只看该作者
原帖由 lugionline 于 2011-4-12 13:54 发表
374在我这里只要19ms

不知道我翻译对了没有

  1. with
  2. d(n) as (select level-1 n from dual connect by level<=8),
  3. cost(i, j, v) as (select d1.n, d2.n, d1.n * 8 + d2.n + 1 from d d1, d d2),
  4. direction(i, j) as
  5. (
  6.         select 1, 1 from dual union
  7.         select 1, 0 from dual union
  8.         select 1, -1 from dual union
  9.         select 0, 1 from dual union
  10.         select 0, -1 from dual ),
  11. path14(i, j, v, s) as
  12. (
  13.         select 0, 0, v,
  14.                 cast('x' as char(64)) s from cost where i = 0 and j = 0
  15.         union all
  16.         select p.i + d.i, p.j + d.j, p.v + c.v,
  17.                 cast(substr(p.s,1, 8 * (p.i + d.i) + p.j + d.j + 1-1)|| 'x'||substr(p.s, 8 * (p.i + d.i) + p.j + d.j + 1+1) as char(64)) s
  18.         from path14 p, direction d, cost c
  19.         where p.i + d.i >= 0 and p.i + d.i < 4 -- 在网格内
  20.                 and p.j + d.j >= 0 and p.j + d.j < 8
  21.                 and substr(p.s, 8 * (p.i + d.i) + p.j + d.j + 1, 1) <> 'x' -- 没访问过
  22.                 and p.i + d.i = c.i and p.j + d.j = c.j -- 取得费用
  23. ),
  24. path85(i, j, v, s) as
  25. (
  26.         select 7, 7, v,
  27.                 cast(substr(lpad(' ',64,' '), 1,8 * 7 + 7 + 1-1)|| 'x' as char(64)) s
  28.         from cost where i = 7 and j = 7
  29.         union all
  30.         select p.i - d.i, p.j - d.j, p.v + c.v,
  31.                 cast(substr(p.s, 1,8 * (p.i - d.i) + p.j - d.j + 1-1)|| 'x'||substr(p.s, 8 * (p.i - d.i) + p.j - d.j + 1+1) as char(64)) s
  32.         from path85 p, direction d, cost c
  33.         where p.i - d.i >= 0 and p.i - d.i >= 4 -- 在网格内
  34.                 and p.j - d.j >= 0 and p.j - d.j < 8
  35.                 and substr(p.s, 8 * (p.i - d.i) + p.j - d.j + 1, 1) <> 'x' -- 没访问过
  36.                 and p.i - d.i = c.i and p.j - d.j = c.j -- 取得费用
  37. ),
  38. pa(j, v) as (select j,v from path14 where i=3),
  39. pb(j, v) as (select j,v from path85 where i=4)
  40. select * from pa, pb
  41. where
  42.         (pa.j = pb.j or pa.j + 1 = pb.j or pa.j - 1 = pb.j)
  43.         and pa.v + pb.v = 374 -- 取值
  44. and rownum=1;

  45. SQL> @c:\downloads\log

  46.          J          V          J          V
  47. ---------- ---------- ---------- ----------
  48.          1         53          2        321
  49. 已用时间:  00: 00: 35.61
复制代码

使用道具 举报

回复
论坛徽章:
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
59#
发表于 2011-4-12 15:10 | 只看该作者
我尝试 12,34,87,65,14,85,18分步做

基本性能是这样的(不考虑<M带来的裁剪):

step, rows count , times(ms)
12,    183 , 15
34,    1464 , 93
14,    5806 , 400
87,    183, 15
65,    1464, 93
85,    5806, 400
18,    0, 800

最终800ms(M比较大的情况),我这里很难再提升了

使用道具 举报

回复
论坛徽章:
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
60#
发表于 2011-4-12 15:13 | 只看该作者
优化关键在于12/34,87/65做join.


  1. WITH                                                                                                  
  2. p12  (srcblock,destblock,tst,pathstr) AS (
  3.   SELECT  /*+ */ a.n,b.n,a.st+b.st,cast(chr(a.n)||chr(b.n) as varchar2(100))
  4.   from grid a , grid b
  5.    where
  6.    a.n=1    -- Start with first block
  7.    and mod(b.n,8) in (1,2)
  8.    and b.n in (
  9.     a.n + 1,
  10.     a.n - 7,
  11.     a.n + 9,
  12.     a.n + 8,
  13.     a.n - 8)  
  14.   UNION ALL
  15.   SELECT
  16.   a.srcblock,b.n,
  17.   a.tst + b.st,--st
  18.   pathstr||chr(b.n)
  19.   FROM  p12 a , (select * from grid where mod(n,8) in (1,2)) b
  20.   WHERE         b.n in (
  21.   a.destblock + 1,
  22.   a.destblock - 7,
  23.   a.destblock + 9,
  24.   a.destblock + 8,
  25.   a.destblock - 8
  26.   ) and b.n!=1
  27.   AND a.tst + b.st <=:M
  28.   and instr(pathstr,chr(n))=0
  29. ),
  30. pp12 as (
  31. select /*+ */ distinct destblock,tst from p12
  32. where mod(destblock,8)=2
  33. ),
  34. p34  (srcblock,destblock,tst,pathstr) AS (
  35.   SELECT   a.n,b.n,a.st+b.st,cast(chr(a.n)||chr(b.n) as varchar2(100))
  36.   from grid a , grid b
  37.    where  mod(a.n,8) =3    -- Start with first block
  38.    and b.n in (
  39.     a.n + 1,
  40.     a.n - 7,
  41.     a.n + 9,
  42.     a.n + 8,
  43.     a.n - 8
  44.    )
  45.    and mod(a.n,8) in (3,4)
  46.   UNION ALL
  47.   SELECT
  48.   a.srcblock,b.n,--出发、到达block
  49.   a.tst + b.st,--st
  50.    pathstr||chr(b.n)
  51. FROM  p34 a , (select * from grid where mod(n,8) in (3,4)) b
  52.   WHERE         b.n in (
  53.   a.destblock + 1,
  54.   a.destblock - 7,
  55.   a.destblock + 9,
  56.   a.destblock + 8,
  57.   a.destblock - 8
  58.   )
  59.   AND a.tst + b.st <:M
  60.   and instr(pathstr,chr(n))=0
  61. ) ,
  62. pp34 as (
  63. select /*+ */ distinct srcblock,destblock,tst from p34
  64. where mod(destblock,8)=4
  65. ) ,
  66. p14 as(
  67. select /*+  use_concat ordered use_hash(a b)   */ distinct b.destblock,a.tst+b.tst  tst
  68. from pp12 a,pp34 b
  69. where
  70.   b.srcblock in (
  71.   a.destblock + 1 ,
  72.   a.destblock - 7 ,
  73.   a.destblock + 9
  74. )
  75.   AND a.tst + b.tst <:M
  76. ),
  77. p87  (srcblock,destblock,tst,pathstr) AS (
  78.   SELECT  /*+ */a.n,b.n,a.st+b.st,cast(chr(a.n)||chr(b.n) as varchar2(100))
  79.   from grid a , grid b
  80.    where  a.n=64    -- Start with last block
  81.    and b.n in (
  82.     a.n - 1,
  83.     a.n - 9,
  84.     a.n + 7,
  85.     a.n + 8,
  86.     a.n - 8
  87.   )
  88.   and mod(b.n,8) in (0,7)
  89.   UNION ALL
  90.   SELECT
  91.   a.srcblock,b.n,--出发、到达block
  92.   a.tst + b.st,--st
  93.   pathstr||chr(b.n)
  94.   FROM  p87 a , (select * from grid where mod(n,8) in (0,7)) b
  95.   WHERE         b.n in (
  96.     a.destblock - 1,
  97.     a.destblock - 9,
  98.     a.destblock + 7,
  99.     a.destblock + 8,
  100.     a.destblock - 8
  101.   ) and b.n!=64
  102.   AND a.tst + b.st <:M
  103.   and instr(pathstr,chr(n))=0
  104. ),
  105. pp87 as (
  106. select /*+ */ distinct destblock,tst from p87
  107. where mod(destblock,8)=7
  108. ),
  109. p65  (srcblock,destblock,tst,pathstr) AS ( --先探测3级内的路径
  110.   SELECT   a.n,b.n,a.st+b.st,cast(chr(a.n)||chr(b.n) as varchar2(100))
  111.   from grid a , grid b
  112.    where  mod(a.n,8) =6    -- Start with first block
  113.    and b.n in (
  114.     a.n - 1,
  115.     a.n - 9,
  116.     a.n + 7,
  117.     a.n + 8,
  118.     a.n - 8
  119.    )
  120.    and mod(a.n,8) in (5,6)
  121.   UNION ALL
  122.   SELECT
  123.   a.srcblock,b.n,--出发、到达block
  124.   a.tst + b.st,--st
  125.    pathstr||chr(b.n)
  126. FROM  p65 a , (select * from grid where mod(n,8) in (5,6)) b
  127.   WHERE         b.n in (
  128.     a.destblock - 1,
  129.     a.destblock - 9,
  130.     a.destblock + 7,
  131.     a.destblock + 8,
  132.     a.destblock - 8
  133.   )
  134.   AND a.tst + b.st <=:M
  135.   and instr(pathstr,chr(n))=0
  136. )
  137. ,
  138. pp65 as (
  139. select /*+ */ distinct srcblock,destblock,tst from p65
  140. where mod(destblock,8)=5
  141. )  ,
  142. p85 as(
  143. select /*+ use_concat ordered use_hash(a b)  */ distinct b.destblock,b.tst+a.tst tst
  144. from pp87 a,pp65 b
  145. where
  146.   b.srcblock in (
  147.   a.destblock - 1 ,
  148.   a.destblock + 7 ,
  149.   a.destblock - 9
  150. )
  151. and b.tst+a.tst<:M
  152. ),
  153. p18 as (
  154. select /*+use_hash(a b)  */'Y' f from p14 a,p85 b
  155. where
  156.   b.destblock in (
  157.   a.destblock + 1 ,
  158.   a.destblock - 7 ,
  159.   a.destblock + 9
  160. ) and  b.tst = :M - a.tst
  161. and rownum = 1
  162. )
  163. select nvl(max(f),'N') from p18  

复制代码

使用道具 举报

回复

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

本版积分规则 发表回复

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