楼主: 〇〇

[转载] 用plsql解立体8数码

[复制链接]
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
11#
发表于 2009-11-18 07:53 | 只看该作者

再装修一下,尽早退出循环:
CREATE OR REPLACE PACKAGE cube_8 AS
  PROCEDURE run_cube(p_x IN NUMBER,p_y IN NUMBER, p_target_layout VARCHAR2);
END cube_8;
/


CREATE OR REPLACE PACKAGE BODY cube_8 AS
  
  TYPE t_str IS TABLE OF VARCHAR2(10) INDEX BY VARCHAR2(9);
  g_added_layout  t_str;
  
  TYPE t_board IS RECORD (
    parent_id  VARCHAR2(10)
   ,layout     VARCHAR2(9)
   ,steps      NUMBER
    );

  TYPE tb_board IS TABLE OF t_board INDEX BY VARCHAR2(10);
  g_board tb_board;
  
  g_target VARCHAR2(9);
  g_found BOOLEAN;

  PROCEDURE show_board (p_start IN VARCHAR2) IS
    lv_id VARCHAR2(9):=p_start;
    lv_layout VARCHAR2(9);
    lv_result t_str;
  BEGIN
   
    WHILE lv_id<>'0' LOOP
       lv_result(lv_result.COUNT+1) := lv_id;
       lv_id := g_board(lv_id).parent_id;
    END LOOP;
   
    FOR i IN REVERSE 1..lv_result.COUNT LOOP
      --lv_layout := TRANSLATE(g_board(lv_result(i)).layout, '1234560', 'WWBBRRE');
      lv_layout := g_board(lv_result(i)).layout;
      dbms_output.put_line('====' ||g_board(lv_result(i)).steps || '====');
      dbms_output.put_line('. ' || substr(lv_layout, 1, 3)||'      '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 1, 3));
      dbms_output.put_line('. ' || substr(lv_layout, 4, 3)||'      '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 4, 3));
      dbms_output.put_line('. ' || substr(lv_layout, 7, 3)||'      '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 7, 3));
      dbms_output.new_line;
    END LOOP;
  END;
  
  PROCEDURE add_board (p_layout VARCHAR2, p_parent_id VARCHAR2, p_steps IN NUMBER)
  AS
     lv_cnt NUMBER := g_board.COUNT+1;
  BEGIN
     g_board(lv_cnt).parent_id := p_parent_id;
     g_board(lv_cnt).layout := p_layout;
     g_board(lv_cnt).steps := p_steps;
     g_added_layout(p_layout):='1';
     
     IF TRANSLATE(p_layout, '1234560', 'WWBBRRE') = g_target THEN
        show_board(lv_cnt);
        g_found := TRUE;
     END IF;
  END add_board;

  PROCEDURE add_next_boards(p_layout IN VARCHAR2, p_parent_id VARCHAR2, p_steps IN NUMBER) IS
    pos NUMBER;
   
    PROCEDURE new_layout(p_layout IN VARCHAR2,a IN NUMBER,b IN NUMBER, p_c1 IN VARCHAR2, p_c2 IN VARCHAR2)
    AS
      lv_new_layout VARCHAR2(9):= substr(p_layout, 1, a - 1)
                                ||p_c1
                                ||substr(p_layout,a + 1,b - a - 1)
                                ||p_c2
                                ||substr(p_layout,b + 1);
  
    BEGIN
      
       BEGIN
          IF g_added_layout(lv_new_layout)='1' THEN
             RETURN;
          END IF;
       EXCEPTION
          WHEN NO_DATA_FOUND THEN
               NULL;
       END;
       add_board(lv_new_layout,p_parent_id,p_steps);
       RETURN;
    END new_layout;
   
  BEGIN
    pos := instr(p_layout, '0');

    -- blank block up movable
    IF pos > 3 THEN
       new_layout(p_layout, pos-3, pos,'0',SUBSTR('645231',SUBSTR(p_layout,pos-3,1),1));
    END IF;
    -- blank block down movable
    IF pos < 7 THEN
       new_layout(p_layout, pos, pos + 3,SUBSTR('645231',SUBSTR(p_layout,pos+3,1),1),'0');
    END IF;
    -- blank block left movable
    IF pos NOT IN (1, 4, 7) THEN
       new_layout(p_layout, pos-1, pos,'0',SUBSTR('351624',SUBSTR(p_layout,pos-1,1),1));
    END IF;
    -- blank block right movable
    IF pos NOT IN (3, 6, 9) THEN
       new_layout(p_layout, pos, pos + 1,SUBSTR('351624',SUBSTR(p_layout,pos+1,1),1),'0');
    END IF;

  END;
  

  PROCEDURE run_cube(p_x IN NUMBER,p_y IN NUMBER, p_target_layout VARCHAR2)
  AS
    lv_current NUMBER;
  BEGIN
                  
    -- empty temporary tables
    g_added_layout.DELETE;
    g_board.DELETE;
    g_found := FALSE;
    g_target := p_target_layout;
   
    add_board(RPAD(LPAD('0',(p_y-1)*3+p_x,'1'),'9','1'),'0',0);
   
    lv_current :=1;
   
    WHILE NOT g_found LOOP
      
      add_next_boards(g_board(lv_current).layout, lv_current,g_board(lv_current).steps+1);
      lv_current := lv_current +1;

      IF lv_current>g_board.COUNT THEN
          dbms_output.put_line('no result!');
          EXIT;
      END IF;
    END LOOP;
  END;
END cube_8;
/



现在第五个用55秒。

使用道具 举报

回复
论坛徽章:
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
12#
 楼主| 发表于 2009-11-18 08:26 | 只看该作者
计算机不动了,好像在交换页面文件还是在自动扩表空间
EXEC cube_8.run_cube(1,2,'WWWEWWWWW');

EXEC cube_8.run_cube(2,1, 'RBWRWWEWW');

EXEC cube_8.run_cube(3,3,'WBWBRERBR');

EXEC cube_8.run_cube(3,3,'BWRBWRBER');

EXEC cube_8.run_cube(2,1,'BBBBRBBRE');

EXEC cube_8.run_cube(1,1,'RRRWWWRRE');

EXEC cube_8.run_cube(2,1,'RRRBWBRRE');

EXEC cube_8.run_cube(3,2,'RRRWEWRRR');

result8.txt

4.7 KB, 下载次数: 6

使用道具 举报

回复
论坛徽章:
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
13#
 楼主| 发表于 2009-11-18 08:27 | 只看该作者
SQL>
SQL> EXEC cube_8.run_cube(1,1,'RRRWWWRRE')
====0====
. 011      EWW
. 111      WWW
. 111      WWW
====1====
. 611      RWW
. 011      EWW
. 111      WWW
====2====
. 611      RWW
. 611      RWW
. 011      EWW
====3====
. 611      RWW
. 611      RWW
. 301      BEW
====4====
. 611      RWW
. 601      REW
. 361      BRW
====5====
. 601      REW
. 661      RRW
. 361      BRW
====6====
. 630      RBE
. 661      RRW
. 361      BRW
====7====
. 636      RBR
. 660      RRE
. 361      BRW
====8====
. 636      RBR
. 604      REB
. 361      BRW
====9====
. 606      RER
. 654      RRB
. 361      BRW
====10====
. 640      RBE
. 654      RRB
. 361      BRW
====11====
. 642      RBW
. 650      RRE
. 361      BRW
====12====
. 642      RBW
. 602      REW
. 361      BRW
====13====
. 642      RBW
. 612      RWW
. 301      BEW
====14====
. 642      RBW
. 612      RWW
. 330      BBE
====15====
. 642      RBW
. 610      RWE
. 334      BBB
====16====
. 640      RBE
. 614      RWB
. 334      BBB
====17====
. 606      RER
. 614      RWB
. 334      BBB
====18====
. 666      RRR
. 604      REB
. 334      BBB
====19====
. 666      RRR
. 654      RRB
. 304      BEB
====20====
. 666      RRR
. 654      RRB
. 360      BRE
====21====
. 666      RRR
. 650      RRE
. 362      BRW
====22====
. 666      RRR
. 602      REW
. 362      BRW
====23====
. 666      RRR
. 042      EBW
. 362      BRW
====24====
. 666      RRR
. 542      RBW
. 062      ERW
====25====
. 666      RRR
. 542      RBW
. 402      BEW
====26====
. 666      RRR
. 502      REW
. 422      BWW
====27====
. 666      RRR
. 022      EWW
. 422      BWW
====28====
. 666      RRR
. 222      WWW
. 022      EWW
====29====
. 666      RRR
. 222      WWW
. 502      REW
====30====
. 666      RRR
. 222      WWW
. 550      RRE

PL/SQL procedure successfully completed.

Elapsed: 00:04:00.09

使用道具 举报

回复
论坛徽章:
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
14#
 楼主| 发表于 2009-11-18 08:47 | 只看该作者
运行完后和现在的内存使用

taskmgr.PNG (8.54 KB, 下载次数: 67)

taskmgr.PNG

taskmgr2.PNG (8.4 KB, 下载次数: 29)

taskmgr2.PNG

result9.txt

10.94 KB, 下载次数: 3

使用道具 举报

回复
论坛徽章:
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
15#
 楼主| 发表于 2009-11-18 09:01 | 只看该作者
原题要求5秒,还有很多人ac
http://acm.pku.edu.cn/JudgeOnline/problem?id=3240
这个只有1道题,1秒

使用道具 举报

回复
论坛徽章:
17
生肖徽章2007版:鸡
日期:2008-01-02 17:35:53ITPUB十周年纪念徽章
日期:2011-11-01 16:21:152011新春纪念徽章
日期:2011-02-18 11:43:332010新春纪念徽章
日期:2010-03-01 11:04:57生肖徽章2007版:鼠
日期:2009-11-29 12:48:34生肖徽章2007版:兔
日期:2009-11-23 16:38:24祖国60周年纪念徽章
日期:2009-10-09 08:28:00生肖徽章2007版:龙
日期:2009-09-10 11:23:342009日食纪念
日期:2009-07-22 09:30:00生肖徽章2007版:猴
日期:2009-06-14 03:09:34
16#
发表于 2009-11-18 09:15 | 只看该作者
开眼界了,的确牛,要好好研究一下

使用道具 举报

回复
论坛徽章:
3
CTO参与奖
日期:2009-01-15 11:42:462010新春纪念徽章
日期:2010-01-04 08:33:08ITPUB十周年纪念徽章
日期:2011-11-01 16:24:04
17#
发表于 2009-11-18 13:54 | 只看该作者
原帖由 newkid 于 2009-11-18 05:28 发表
抓到虫了,addm的过程add_board里面少了这么一句:
g_boards_hash(layout) := '1';

还有:IF g_boards(g_cur_board_id).step >= 30 THEN
必须改为: IF g_boards(g_cur_board_id).step > 30 THEN
否则第六个出不来。

我们的方法其实很类似,就是我用编码判断比较简便一些。
改过之后,addm的程序运行第四个花了20秒,第五个1:32,第六个2:22; 用我的方法第四个15秒,第五个1:12, 第六个1:49.

第六个例子hash数组达到了3179362,两个程序不能在同一SESSION运行,否则报内存不够。


你说的没错儿。按照你的建议修改如下:

/* Oracle Database 10g Release 10.2.0.1.0 */
create or replace
PACKAGE cube_pkg IS
  PROCEDURE run_board(file_name VARCHAR2);
END cube_pkg;
/
create or replace
PACKAGE BODY cube_pkg IS
  g_start_time number; -- caculate timing
  g_rindex BINARY_INTEGER;
  g_slno   BINARY_INTEGER;
  TYPE t_hash IS TABLE OF CHAR(1) INDEX BY VARCHAR2(18);
  TYPE t_board IS RECORD(
    layout    VARCHAR2(18),
    parent_id PLS_INTEGER,
    step      NUMBER);
  TYPE t_board_tab IS TABLE OF t_board;
  g_boards_hash  t_hash;
  g_boards       t_board_tab := t_board_tab();
  g_board_init   t_board;
  g_target       VARCHAR2(9); -- target layout
  g_cur_board_id NUMBER;
  g_steps        NUMBER;

  -- roll cube horizontally or vertiaclly, get next state of cube
  PROCEDURE roll_cube(top   IN OUT NOCOPY VARCHAR2,
                      RIGHT IN OUT NOCOPY VARCHAR2,
                      dir   IN VARCHAR2 DEFAULT 'H') IS
    c CHAR(1);
  BEGIN
    IF dir = 'H' THEN
      -- roll horizontally
      c     := top;
      top   := RIGHT;
      RIGHT := c;
    ELSE
      -- dir = 'V' -- roll vertiaclly
      FOR i IN 1 .. 3 LOOP
        c := CASE i
               WHEN 1 THEN
                'R'
               WHEN 2 THEN
                'W'
               WHEN 3 THEN
                'B'
             END;
        IF c <> top AND c <> RIGHT THEN
          top := c;
          EXIT;
        END IF;
      END LOOP;
    END IF;
  END roll_cube;

  FUNCTION new_layout(layout VARCHAR2, a NUMBER, b NUMBER) RETURN VARCHAR2 IS
    cube_top   CHAR(1);
    cube_right CHAR(1);
    cube_pos   NUMBER;
    layout_new VARCHAR2(20);
  BEGIN
    -- assert(a - b IN (1, -1, 3, -3), 'a-b in (1,-1,3,-3)');
    cube_pos   := CASE substr(layout, a, 1)
                    WHEN 'E' THEN
                     b
                    ELSE
                     a
                  END;
    cube_top   := substr(layout, cube_pos, 1);
    cube_right := substr(layout, cube_pos + 9, 1);
    roll_cube(cube_top,
              cube_right,
              CASE WHEN a - b IN (1, -1) THEN 'H' ELSE 'V' END);
    layout_new := substr(layout, 1, cube_pos - 1) || cube_top ||
                  substr(layout, cube_pos + 1, 9 - 1) || cube_right ||
                  substr(layout, cube_pos + 9 + 1);
    -- assert(a < b, 'a<b');
    RETURN substr(layout_new, 1, a - 1) || substr(layout_new, b, 1) || substr(layout_new, a + 1, b - a - 1) ||
                                substr(layout_new, a, 1) || substr(layout_new, b + 1, (a + 9) - b - 1) ||
                                substr(layout_new, b + 9, 1) || substr(layout_new, (a + 9) + 1, b - a - 1) ||
                                substr(layout_new, a + 9, 1) || substr(layout_new, (b + 9) + 1);
  END;
  PROCEDURE add_board(layout VARCHAR2) IS
  BEGIN
    BEGIN
      IF g_boards_hash(layout) = '1' THEN
        -- already reached
        RETURN;
      END IF;
    EXCEPTION
      WHEN no_data_found THEN
        NULL;
    END;
    g_boards.extend;
    g_boards(g_boards.count).layout := layout;
    g_boards(g_boards.count).parent_id := g_cur_board_id;
    g_boards(g_boards.count).step := g_boards(g_cur_board_id).step + 1;
    g_boards_hash(layout):='1';
    -- update v$session_longpos
    dbms_application_info.set_session_longops(g_rindex,
                                              g_slno,
                                              'CUBE_PKG',
                                              0,
                                              0,
                                              g_boards.count,
                                              15116544);
  
  END add_board;
  PROCEDURE add_next_boards IS
  
    layout    VARCHAR2(18) := g_boards(g_cur_board_id).layout;
    empty_pos INTEGER := instr(layout, 'E');
  BEGIN
    -- blank block up movable
    IF empty_pos > 3 THEN
      add_board(new_layout(layout, empty_pos - 3, empty_pos));
    END IF;
    -- blank block down movable
    IF empty_pos < 7 THEN
      add_board(new_layout(layout, empty_pos, empty_pos + 3));
    END IF;
    -- blank block left movable
    IF empty_pos NOT IN (1, 4, 7) THEN
      add_board(new_layout(layout, empty_pos - 1, empty_pos));
    END IF;
    -- blank block right movable
    IF empty_pos NOT IN (3, 6, 9) THEN
      add_board(new_layout(layout, empty_pos, empty_pos + 1));
    END IF;
  END;

  PROCEDURE proc_board IS
  BEGIN
    WHILE g_cur_board_id <= g_boards.count LOOP
      IF substr(g_boards(g_cur_board_id).layout, 1, 9) = g_target THEN
        -- reach target
        dbms_output.put_line(g_boards(g_cur_board_id).step);
        RETURN;
      END IF;
      IF g_boards(g_cur_board_id).step > 30 THEN
        EXIT; -- exceed 30 step
      END IF;
      add_next_boards;
      -- dequeue
      g_cur_board_id := g_cur_board_id + 1;
    END LOOP;
    dbms_output.put_line('-1');
  END;
  FUNCTION init_board(fp utl_file.file_type) RETURN BOOLEAN IS
    x         NUMBER;
    y         NUMBER;
    empty_pos NUMBER;
    layout CONSTANT VARCHAR2(18) := 'WWWWWWWWWBBBBBBBBB';
    str VARCHAR2(128);
  BEGIN
    utl_file.get_line(fp, str);
    x := to_number(substr(str, 1, instr(str, ' ') - 1));
    y := to_number(substr(str, instr(str, ' ') + 1));
    IF x = 0 AND y = 0 THEN
      RETURN FALSE;
    END IF;
    -- set initial board
    empty_pos              := (y - 1) * 3 + x;
    g_board_init.layout    := substr(layout, 1, empty_pos - 1) || 'E' ||
                              substr(layout,
                                     empty_pos + 1,
                                     (9 + empty_pos) - (empty_pos + 1)) || 'E' ||
                              substr(layout, 9 + empty_pos + 1);
    g_board_init.parent_id := 0;
  
    -- read target layout
    g_target := NULL;
    FOR i IN 1 .. 3 LOOP
      utl_file.get_line(fp, str);
      g_target := g_target || REPLACE(str, ' ', NULL);
    END LOOP;
    g_boards.delete; -- empty temporary nested table
    g_boards_hash.delete;
    g_cur_board_id := 1; -- restore current board id
    g_steps        := 0;
    g_boards.extend;
    g_boards(1).layout := g_board_init.layout;
    g_boards(1).parent_id := g_board_init.parent_id;
    g_boards(1).step := 0;
    g_boards_hash(g_board_init.layout) := '1';
    RETURN TRUE;
  END init_board;

  PROCEDURE run_board(file_name VARCHAR2) IS
    f1 utl_file.file_type;
  BEGIN
    -- dbms_application_info variables
    g_rindex := dbms_application_info.set_session_longops_nohint;
  
    f1 := utl_file.fopen('ITPUB', file_name, 'r', 128);
    WHILE init_board(f1) LOOP
      g_start_time:= dbms_utility.get_time;
      proc_board;
      dbms_output.put_line('time='||(dbms_utility.get_time-g_start_time)/100.0||
        's, g_boards.count='||g_boards.count);
    END LOOP;
    utl_file.fclose(f1);
  EXCEPTION
    WHEN utl_file.invalid_operation OR utl_file.invalid_path THEN
      dbms_output.put_line('Can not open input file!');
    WHEN OTHERS THEN
      IF utl_file.is_open(f1) THEN
        utl_file.fclose(f1);
      END IF;
      RAISE;
  END run_board;
END cube_pkg;
/

cube_pkg.zip (2.27 KB, 下载次数: 4)

机器配置:

Processor: Intel(R) Core(TM)2 Duo CPU E7400 @ 2.8Gz(2 CPUs)
Memory: 2036MB RAM

运行结果如下:
TEST@orcl> exec cube_pkg.run_board('input.txt');
0
time=0s, g_boards.count=1
3
time=0s, g_boards.count=25
13
time=.14s, g_boards.count=4768
23
time=21.42s, g_boards.count=592985
29
time=95.65s, g_boards.count=2113791
30
time=161.64s, g_boards.count=3179362
-1
time=126.97s, g_boards.count=2653591
-1
time=126.92s, g_boards.count=2653591

PL/SQL 过程已成功完成。

已用时间:  00: 10: 19.76

使用道具 举报

回复
论坛徽章:
3
CTO参与奖
日期:2009-01-15 11:42:462010新春纪念徽章
日期:2010-01-04 08:33:08ITPUB十周年纪念徽章
日期:2011-11-01 16:24:04
18#
发表于 2009-11-18 13:58 | 只看该作者
原帖由 newkid 于 2009-11-18 07:53 发表

再装修一下,尽早退出循环:
CREATE OR REPLACE PACKAGE cube_8 AS
  PROCEDURE run_cube(p_x IN NUMBER,p_y IN NUMBER, p_target_layout VARCHAR2);
END cube_8;
/


CREATE OR REPLACE PACKAGE BODY cube_8 AS
  
  TYPE t_str IS TABLE OF VARCHAR2(10) INDEX BY VARCHAR2(9);
  g_added_layout  t_str;
  
  TYPE t_board IS RECORD (
    parent_id  VARCHAR2(10)
   ,layout     VARCHAR2(9)
   ,steps      NUMBER
    );

  TYPE tb_board IS TABLE OF t_board INDEX BY VARCHAR2(10);
  g_board tb_board;
  
  g_target VARCHAR2(9);
  g_found BOOLEAN;

  PROCEDURE show_board (p_start IN VARCHAR2) IS
    lv_id VARCHAR2(9):=p_start;
    lv_layout VARCHAR2(9);
    lv_result t_str;
  BEGIN
   
    WHILE lv_id'0' LOOP
       lv_result(lv_result.COUNT+1) := lv_id;
       lv_id := g_board(lv_id).parent_id;
    END LOOP;
   
    FOR i IN REVERSE 1..lv_result.COUNT LOOP
      --lv_layout := TRANSLATE(g_board(lv_result(i)).layout, '1234560', 'WWBBRRE');
      lv_layout := g_board(lv_result(i)).layout;
      dbms_output.put_line('====' ||g_board(lv_result(i)).steps || '====');
      dbms_output.put_line('. ' || substr(lv_layout, 1, 3)||'      '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 1, 3));
      dbms_output.put_line('. ' || substr(lv_layout, 4, 3)||'      '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 4, 3));
      dbms_output.put_line('. ' || substr(lv_layout, 7, 3)||'      '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 7, 3));
      dbms_output.new_line;
    END LOOP;
  END;
  
  PROCEDURE add_board (p_layout VARCHAR2, p_parent_id VARCHAR2, p_steps IN NUMBER)
  AS
     lv_cnt NUMBER := g_board.COUNT+1;
  BEGIN
     g_board(lv_cnt).parent_id := p_parent_id;
     g_board(lv_cnt).layout := p_layout;
     g_board(lv_cnt).steps := p_steps;
     g_added_layout(p_layout):='1';
     
     IF TRANSLATE(p_layout, '1234560', 'WWBBRRE') = g_target THEN
        show_board(lv_cnt);
        g_found := TRUE;
     END IF;
  END add_board;

  PROCEDURE add_next_boards(p_layout IN VARCHAR2, p_parent_id VARCHAR2, p_steps IN NUMBER) IS
    pos NUMBER;
   
    PROCEDURE new_layout(p_layout IN VARCHAR2,a IN NUMBER,b IN NUMBER, p_c1 IN VARCHAR2, p_c2 IN VARCHAR2)
    AS
      lv_new_layout VARCHAR2(9):= substr(p_layout, 1, a - 1)
                                ||p_c1
                                ||substr(p_layout,a + 1,b - a - 1)
                                ||p_c2
                                ||substr(p_layout,b + 1);
  
    BEGIN
      
       BEGIN
          IF g_added_layout(lv_new_layout)='1' THEN
             RETURN;
          END IF;
       EXCEPTION
          WHEN NO_DATA_FOUND THEN
               NULL;
       END;
       add_board(lv_new_layout,p_parent_id,p_steps);
       RETURN;
    END new_layout;
   
  BEGIN
    pos := instr(p_layout, '0');

    -- blank block up movable
    IF pos > 3 THEN
       new_layout(p_layout, pos-3, pos,'0',SUBSTR('645231',SUBSTR(p_layout,pos-3,1),1));
    END IF;
    -- blank block down movable
    IF pos < 7 THEN
       new_layout(p_layout, pos, pos + 3,SUBSTR('645231',SUBSTR(p_layout,pos+3,1),1),'0');
    END IF;
    -- blank block left movable
    IF pos NOT IN (1, 4, 7) THEN
       new_layout(p_layout, pos-1, pos,'0',SUBSTR('351624',SUBSTR(p_layout,pos-1,1),1));
    END IF;
    -- blank block right movable
    IF pos NOT IN (3, 6, 9) THEN
       new_layout(p_layout, pos, pos + 1,SUBSTR('351624',SUBSTR(p_layout,pos+1,1),1),'0');
    END IF;

  END;
  

  PROCEDURE run_cube(p_x IN NUMBER,p_y IN NUMBER, p_target_layout VARCHAR2)
  AS
    lv_current NUMBER;
  BEGIN
                  
    -- empty temporary tables
    g_added_layout.DELETE;
    g_board.DELETE;
    g_found := FALSE;
    g_target := p_target_layout;
   
    add_board(RPAD(LPAD('0',(p_y-1)*3+p_x,'1'),'9','1'),'0',0);
   
    lv_current :=1;
   
    WHILE NOT g_found LOOP
      
      add_next_boards(g_board(lv_current).layout, lv_current,g_board(lv_current).steps+1);
      lv_current := lv_current +1;

      IF lv_current>g_board.COUNT THEN
          dbms_output.put_line('no result!');
          EXIT;
      END IF;
    END LOOP;
  END;
END cube_8;
/



现在第五个用55秒。


旋转、移位效率比较高。但不知为什么,总报内存不够。

我的机器配置:

Processor: Intel(R) Core(TM)2 Duo CPU E7400 @ 2.8Gz(2 CPUs)
Memory: 2036MB RAM

测试:
EXEC cube_8.run_cube(1,2,'WWWEWWWWW');
EXEC cube_8.run_cube(2,1,'RBWRWWEWW');
EXEC cube_8.run_cube(3,3,'WBWBRERBR');
EXEC cube_8.run_cube(3,3,'BWRBWRBER');
EXEC cube_8.run_cube(2,1,'BBBBRBBRE');
EXEC cube_8.run_cube(1,1,'RRRWWWRRE');
EXEC cube_8.run_cube(2,1,'RRRBWBRRE');
EXEC cube_8.run_cube(3,2,'RRRWEWRRR');

结果:

TEST@orcl> EXEC cube_8.run_cube(1,2,'WWWEWWWWW');
====0====
. 111      WWW
. 011      EWW
. 111      WWW

PL/SQL 过程已成功完成。

已用时间:  00: 00: 00.20
TEST@orcl> EXEC cube_8.run_cube(2,1,'RBWRWWEWW');
====0====
. 101      WEW
. 111      WWW
. 111      WWW
====1====
. 031      EBW
. 111      WWW
. 111      WWW
====2====
. 631      RBW
. 011      EWW
. 111      WWW
====3====
. 631      RBW
. 611      RWW
. 011      EWW

PL/SQL 过程已成功完成。

已用时间:  00: 00: 00.04
TEST@orcl> EXEC cube_8.run_cube(3,3,'WBWBRERBR');
====0====
. 111      WWW
. 111      WWW
. 110      WWE
====1====
. 111      WWW
. 110      WWE
. 116      WWR
====2====
. 111      WWW
. 103      WEB
. 116      WWR
====3====
. 111      WWW
. 163      WRB
. 106      WER
====4====
. 111      WWW
. 163      WRB
. 036      EBR
====5====
. 111      WWW
. 063      ERB
. 636      RBR
====6====
. 111      WWW
. 403      BEB
. 636      RBR
====7====
. 101      WEW
. 463      BRB
. 636      RBR
====8====
. 031      EBW
. 463      BRB
. 636      RBR
====9====
. 231      WBW
. 063      ERB
. 636      RBR
====10====
. 231      WBW
. 403      BEB
. 636      RBR
====11====
. 231      WBW
. 453      BRB
. 606      RER
====12====
. 231      WBW
. 453      BRB
. 640      RBE
====13====
. 231      WBW
. 450      BRE
. 645      RBR

PL/SQL 过程已成功完成。

已用时间:  00: 00: 00.20
TEST@orcl> EXEC cube_8.run_cube(3,3,'BWRBWRBER');
====0====
. 111      WWW
. 111      WWW
. 110      WWE
====1====
. 111      WWW
. 110      WWE
. 116      WWR
====2====
. 111      WWW
. 103      WEB
. 116      WWR
====3====
. 111      WWW
. 163      WRB
. 106      WER
====4====
. 111      WWW
. 163      WRB
. 036      EBR
====5====
. 111      WWW
. 063      ERB
. 636      RBR
====6====
. 011      EWW
. 663      RRB
. 636      RBR
====7====
. 301      BEW
. 663      RRB
. 636      RBR
====8====
. 311      BWW
. 603      REB
. 636      RBR
====9====
. 311      BWW
. 043      EBB
. 636      RBR
====10====
. 011      EWW
. 543      RBB
. 636      RBR
====11====
. 301      BEW
. 543      RBB
. 636      RBR
====12====
. 321      BWW
. 503      REB
. 636      RBR
====13====
. 321      BWW
. 553      RRB
. 606      RER
====14====
. 321      BWW
. 553      RRB
. 046      EBR
====15====
. 321      BWW
. 053      ERB
. 346      BBR
====16====
. 321      BWW
. 203      WEB
. 346      BBR
====17====
. 321      BWW
. 210      WWE
. 346      BBR
====18====
. 320      BWE
. 216      WWR
. 346      BBR
====19====
. 305      BER
. 216      WWR
. 346      BBR
====20====
. 015      EWR
. 216      WWR
. 346      BBR
====21====
. 415      BWR
. 016      EWR
. 346      BBR
====22====
. 415      BWR
. 306      BER
. 346      BBR
====23====
. 415      BWR
. 326      BWR
. 306      BER

PL/SQL 过程已成功完成。

已用时间:  00: 00: 11.01
TEST@orcl> EXEC cube_8.run_cube(2,1,'BBBBRBBRE');
BEGIN cube_8.run_cube(2,1,'BBBBRBBRE'); END;

*
第 1 行出现错误:
ORA-06500: PL/SQL: 存储错误
ORA-04030: 在尝试分配 16396 字节 (koh-kghu sessi,pmucalm coll) 时进程内存不足
ORA-06512: 在 "TEST.CUBE_8", line 44
ORA-06512: 在 "TEST.CUBE_8", line 76
ORA-06512: 在 "TEST.CUBE_8", line 85
ORA-06512: 在 "TEST.CUBE_8", line 120
ORA-06512: 在 line 1


已用时间:  00: 00: 40.21
TEST@orcl> EXEC cube_8.run_cube(1,1,'RRRWWWRRE');
BEGIN cube_8.run_cube(1,1,'RRRWWWRRE'); END;

*
第 1 行出现错误:
ORA-04030: 在尝试分配 4108 字节 (PLS non-lib hp,pdzfM60_Make) 时进程内存不足


已用时间:  00: 00: 00.00
TEST@orcl> EXEC cube_8.run_cube(2,1,'RRRBWBRRE');
BEGIN cube_8.run_cube(2,1,'RRRBWBRRE'); END;

*
第 1 行出现错误:
ORA-04030: 在尝试分配 4108 字节 (PLS non-lib hp,pdzfM60_Make) 时进程内存不足


已用时间:  00: 00: 00.00
TEST@orcl> EXEC cube_8.run_cube(3,2,'RRRWEWRRR');
BEGIN cube_8.run_cube(3,2,'RRRWEWRRR'); END;

*
第 1 行出现错误:
ORA-04030: 在尝试分配 4108 字节 (PLS non-lib hp,pdzfM60_Make) 时进程内存不足


已用时间:  00: 00: 00.01

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
19#
发表于 2009-11-18 22:32 | 只看该作者

回复 #18 addm 的帖子

我的机器也是2.4GCPU 2GRAM, ORACLE参数都是缺省的,难道是我人品较好?你运行自己的程序有没有问题?
第六个30步的例子:
EXEC cube_8.run_cube(1,1,'RRRWWWRRE');
====0====
. 011      EWW
. 111      WWW
. 111      WWW
====1====
. 611      RWW
. 011      EWW
. 111      WWW
====2====
. 611      RWW
. 611      RWW
. 011      EWW
====3====
. 611      RWW
. 611      RWW
. 301      BEW
====4====
. 611      RWW
. 601      REW
. 361      BRW
====5====
. 601      REW
. 661      RRW
. 361      BRW
====6====
. 630      RBE
. 661      RRW
. 361      BRW
====7====
. 636      RBR
. 660      RRE
. 361      BRW
====8====
. 636      RBR
. 604      REB
. 361      BRW
====9====
. 606      RER
. 654      RRB
. 361      BRW
====10====
. 640      RBE
. 654      RRB
. 361      BRW
====11====
. 642      RBW
. 650      RRE
. 361      BRW
====12====
. 642      RBW
. 602      REW
. 361      BRW
====13====
. 642      RBW
. 612      RWW
. 301      BEW
====14====
. 642      RBW
. 612      RWW
. 330      BBE
====15====
. 642      RBW
. 610      RWE
. 334      BBB
====16====
. 640      RBE
. 614      RWB
. 334      BBB
====17====
. 606      RER
. 614      RWB
. 334      BBB
====18====
. 666      RRR
. 604      REB
. 334      BBB
====19====
. 666      RRR
. 654      RRB
. 304      BEB
====20====
. 666      RRR
. 654      RRB
. 360      BRE
====21====
. 666      RRR
. 650      RRE
. 362      BRW
====22====
. 666      RRR
. 602      REW
. 362      BRW
====23====
. 666      RRR
. 042      EBW
. 362      BRW
====24====
. 666      RRR
. 542      RBW
. 062      ERW
====25====
. 666      RRR
. 542      RBW
. 402      BEW
====26====
. 666      RRR
. 502      REW
. 422      BWW
====27====
. 666      RRR
. 022      EWW
. 422      BWW
====28====
. 666      RRR
. 222      WWW
. 022      EWW
====29====
. 666      RRR
. 222      WWW
. 502      REW
====30====
. 666      RRR
. 222      WWW
. 550      RRE

PL/SQL procedure successfully completed.

Elapsed: 00:01:34.04
第二个数组改用BOOLEAN型,结果差不多。
-------------
我猜到原因了,你应该是运行自己的程序后用同一个SESSION再运行我的,导致内存不够。
在两个程序退出地方加了数组的DELETE,和DBMS_SESSION.FREE_UNUSED_USER_MEMORY; 内村就被释放,可以反复运行也不致于出错。

[ 本帖最后由 newkid 于 2009-11-19 04:28 编辑 ]

使用道具 举报

回复
论坛徽章:
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
20#
 楼主| 发表于 2009-11-19 08:57 | 只看该作者
和c编程差不多了,还要自己释放内存

使用道具 举报

回复

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

本版积分规则 发表回复

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