*&———————————————————————*
*& Report ZEIGHTQUEEN *
*& Date :2007.09.04 *
*&———————————————————————*
*八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世
*纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不
*能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多
*少种摆法。
*高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的
*解,后来有人用图论的方法解出92种结果。
*&———————————————————————*
REPORT zeightqueen .
TYPES: BEGIN OF itab,
lines TYPE n LENGTH 8,
END OF itab.
DATA: gt_itab TYPE STANDARD TABLE OF itab WITH HEADER LINE.
DATA: g_line TYPE n LENGTH 1 VALUE ‘1’, “行
g_row TYPE n LENGTH 1 VALUE ‘1’, “列
flag TYPE c,
g_num TYPE i.
START-OF-SELECTION.
DO.
IF g_line = ‘9’.
EXIT.
ENDIF.
**初始化第一行
PERFORM get_stru USING g_line
CHANGING gt_itab.
CLEAR: gt_itab[].
APPEND gt_itab.
g_line = g_line + 1.
**递归主体FORM
PERFORM main_form USING g_line
g_row
CHANGING flag.
ENDDO.
*&———————————————————————*
*& Form main_form
*&———————————————————————*
* text
*———————————————————————-*
* –>P_G_Y text
* <–P_FLAG text
*———————————————————————-*
FORM main_form USING p_line
p_row
CHANGING p_flag.
DATA: l_line TYPE i,
l_row TYPE i,
l_flag TYPE c.
**从当前行的下一行的第一个位置开始CHECK
l_line = 1.
l_row = p_row + 1.
DO.
**CHECK到本行最后一个位置
IF l_line = ‘9’.
p_flag = l_flag.
EXIT.
ENDIF.
**CHECK到最后一行
IF l_row = ‘9’.
p_flag = ‘S’.
EXIT.
ENDIF.
**CHECK FROM
PERFORM check_line_row USING l_line l_row
CHANGING l_flag.
IF l_flag = ‘S’.
**此位置可用
PERFORM get_stru USING l_line
CHANGING gt_itab.
APPEND gt_itab.
IF l_row = ‘8’.
**如果已经CHECK满8行,则输出
PERFORM write_itab.
l_line = l_line + 1.
DELETE gt_itab INDEX l_row.
ELSE.
**未满8行,继续CHECK下一行
PERFORM main_form USING l_line
l_row
CHANGING l_flag.
IF l_flag = ‘F’.
l_line = l_line + 1.
DELETE gt_itab INDEX l_row.
ELSE.
l_line = l_line + 1.
DELETE gt_itab INDEX l_row.
ENDIF.
ENDIF.
**此位置不可用,CHECK下一位置
ELSE.
l_flag = ‘F’.
l_line = l_line + 1.
ENDIF.
ENDDO.
ENDFORM. ” main_form
*&———————————————————————*
*& Form check_line_row
*&———————————————————————*
* text
*———————————————————————-*
* –>P_L_LINE text
* –>P_L_ROW text
* <–P_L_FLAG text
*———————————————————————-*
FORM check_line_row USING p_line
p_row
CHANGING p_flag.
DATA: l_row TYPE i,
l_line TYPE i,
l_before_p TYPE i,
l_after_p TYPE i.
l_row = p_row.
DO.
l_row = l_row – 1.
IF l_row = ‘0’.
EXIT.
ENDIF.
READ TABLE gt_itab INDEX l_row.
IF sy-subrc = 0.
**从最近的一行,一行一行向上读取
PERFORM get_line USING gt_itab
CHANGING l_line.
l_before_p = l_line + ( p_row – l_row ). “在P_LINE P_ROW之前
l_after_p = l_line – ( p_row – l_row ). “在P_LINE P_ROW之后
**在同一直线上则P_FLAG = ‘F’否则为’S’
IF p_line = l_line.
p_flag = ‘F’.
EXIT.
ELSEIF p_line = l_before_p.
p_flag = ‘F’.
EXIT.
ELSEIF p_line = l_after_p.
p_flag = ‘F’.
EXIT.
ELSE.
p_flag = ‘S’.
ENDIF.
ENDIF.
ENDDO.
ENDFORM. ” check_line_row
*&———————————————————————*
*& Form get_line
*&———————————————————————*
* text
*———————————————————————-*
* –>P_GT_ITAB text
* <–P_L_LINE text
*———————————————————————-*
FORM get_line USING p_itab
CHANGING p_line.
**从一行只有0和1组成的字符串中获取1的位置
**例如:’01000000’,此时 P_LINE = ‘2’
CASE p_itab.
WHEN ‘10000000’.
p_line = 1.
WHEN ‘01000000’.
p_line = 2.
WHEN ‘00100000’.
p_line = 3.
WHEN ‘00010000’.
p_line = 4.
WHEN ‘00001000’.
p_line = 5.
WHEN ‘00000100’.
p_line = 6.
WHEN ‘00000010’.
p_line = 7.
WHEN ‘00000001’.
p_line = 8.
WHEN OTHERS.
**ERROR
ENDCASE.
ENDFORM. ” get_line
*&———————————————————————*
*& Form get_stru
*&———————————————————————*
* text
*———————————————————————-*
* –>P_L_LINE text
* <–P_GT_ITAB text
*———————————————————————-*
FORM get_stru USING p_line
CHANGING p_itab.
**根据P_LINE的数值生成一条由1和0组织的字符串
**例如:P_LINE = ‘2’则P_ITAB = ‘01000000’
CASE p_line.
WHEN ‘1’.
p_itab = ‘10000000’.
WHEN ‘2’.
p_itab = ‘01000000’.
WHEN ‘3’.
p_itab = ‘00100000’.
WHEN ‘4’.
p_itab = ‘00010000’.
WHEN ‘5’.
p_itab = ‘00001000’.
WHEN ‘6’.
p_itab = ‘00000100’.
WHEN ‘7’.
p_itab = ‘00000010’.
WHEN ‘8’.
p_itab = ‘00000001’.
WHEN OTHERS.
**ERROR
ENDCASE.
ENDFORM. ” get_stru
*&———————————————————————*
*& Form write_itab
*&———————————————————————*
* text
*———————————————————————-*
* –> p1 text
* <– p2 text
*———————————————————————-*
FORM write_itab .
DATA: l_num TYPE i,
l_box1 TYPE c,
l_box2 TYPE c,
l_box3 TYPE c,
l_box4 TYPE c,
l_box5 TYPE c,
l_box6 TYPE c,
l_box7 TYPE c,
l_box8 TYPE c.
g_num = g_num + 1.
WRITE / g_num.
LOOP AT gt_itab.
IF gt_itab+0(1) = ‘0’.
l_box1 = ”.
ELSEIF gt_itab+0(1) = ‘1’.
l_box1 = ‘X’.
ENDIF.
IF gt_itab+1(1) = ‘0’.
l_box2 = ”.
ELSEIF gt_itab+1(1) = ‘1’.
l_box2 = ‘X’.
ENDIF.
IF gt_itab+2(1) = ‘0’.
l_box3 = ”.
ELSEIF gt_itab+2(1) = ‘1’.
l_box3 = ‘X’.
ENDIF.
IF gt_itab+3(1) = ‘0’.
l_box4 = ”.
ELSEIF gt_itab+3(1) = ‘1’.
l_box4 = ‘X’.
ENDIF.
IF gt_itab+4(1) = ‘0’.
l_box5 = ”.
ELSEIF gt_itab+4(1) = ‘1’.
l_box5 = ‘X’.
ENDIF.
IF gt_itab+5(1) = ‘0’.
l_box6 = ”.
ELSEIF gt_itab+5(1) = ‘1’.
l_box6 = ‘X’.
ENDIF.
IF gt_itab+6(1) = ‘0’.
l_box7 = ”.
ELSEIF gt_itab+6(1) = ‘1’.
l_box7 = ‘X’.
ENDIF.
IF gt_itab+7(1) = ‘0’.
l_box8 = ”.
ELSEIF gt_itab+7(1) = ‘1’.
l_box8 = ‘X’.
ENDIF.
WRITE: / l_box1 AS CHECKBOX INPUT OFF,
l_box2 AS CHECKBOX INPUT OFF,
l_box3 AS CHECKBOX INPUT OFF,
l_box4 AS CHECKBOX INPUT OFF,
l_box5 AS CHECKBOX INPUT OFF,
l_box6 AS CHECKBOX INPUT OFF,
l_box7 AS CHECKBOX INPUT OFF,
l_box8 AS CHECKBOX INPUT OFF.
ENDLOOP.
ENDFORM. ” write_itab