国际象棋中马的遍历问题

国际象棋中马的遍历问题

我们数据结构课布置了一道题,供大家参阅。
设计一算法,要求如下:
国际象棋中,马按规则从任一点开始将所有格跳过一次(不重复)。

我的算法分析如下:

国际象棋马的走法:先直走或横走一格,再沿离开原来格子的方向斜走一个,合起来为一步棋;国际象棋棋盘黑白交错,格数8×8,根据马的走法,它只能从白格走向黑格,再从黑格走向白格,与此类推。
格子具有集合性,故考虑使用无向图来表示格子及其间关系;以邻接表作为该无向图中结点与相邻8个结点(4黑4白)的存储结构;以顶点表存储格子,每格为顶点表中一结点,其指针域有二,左指针链接黑格邻接表,右指针链接白格邻接表,其结点域为访问标识,访问过则为1,未访问为0;如用c实现,顶点表的头结点(下标为0的数组元素)不用,用来标识每一步的访问方向(先黑后黑或者先白后白)。
(b=black,w=white)
b1 w1 b2 w2
w3 b3 w4 b4
b5 w5 b6 w6
w7 b8 w8 b8
以b3为顶点,得顶点表与邻接表片断如下
...
b6<--b5<--b2<--b1<--[b3]-->;w1-->;w3-->;w4-->;w5
...
采用图的深度遍历算法,以方向标识的取值作为约束条件,每两个半步置值(0/1),以访问标识作为是否访问该结点或跳至下一结点的判断条件,访问所有的结点(可加一计数因子或直接在头顶点开多一域来计数)。

这样便可得到遍历的一条途径。如想得到所有可能的途径,可以在这个算法基础上加以扩展。

综合起来,使用到的算法的核心部分是传统的图深度遍历法,并无什么新鲜之处。
请大家多多指点,评价一下我的算法。

另外,有哪位兄弟能用perl实现呢?
国际象棋马的走法:
http://www.tianwai.com/belllee/chess/m.htm
写了个不成功的,但实在弄不明白为什么不行。
#!/usr/bin/perl -w
%0=( 0,"00", 1,"01", 2,"02", 3,"03", 4,"04", 5,"05", 6,"06", 7,"07" );
%1=( 0,"10", 1,"11", 2,"12", 3,"13", 4,"14", 5,"15", 6,"16", 7,"17" );
%2=( 0,"20", 1,"21", 2,"22", 3,"23", 4,"24", 5,"25", 6,"26", 7,"27" );
%3=( 0,"30", 1,"31", 2,"32", 3,"33", 4,"34", 5,"35", 6,"36", 7,"37" );
%4=( 0,"40", 1,"41", 2,"42", 3,"43", 4,"44", 5,"45", 6,"46", 7,"47" );
%5=( 0,"50", 1,"51", 2,"52", 3,"53", 4,"54", 5,"55", 6,"56", 7,"57" );
%6=( 0,"60", 1,"61", 2,"62", 3,"63", 4,"64", 5,"65", 6,"66", 7,"67" );
%7=( 0,"70", 1,"71", 2,"72", 3,"73", 4,"74", 5,"75", 6,"76", 7,"77" );
srand; $i= int (rand( 8 )) ; $j = int (rand( 8 )) ; delete${$i}{$j};
for ($count=1;$count<=63;$count++) {
if (($i+1) =~ /[0-7]/ && ($j+2) =~ /[0-7]/ ) {delete${($i+1)}{($j+2)}; @a=%{($i+1)} ; print "@a\n"; }
elsif (($i+1) =~ /[0-7]/ && ($j-2) =~ /[0-7]/ ) {delete${($i+1)}{($j-2)}; @a=%{($i+1)} ; print "@a\n"; }
elsif (($i-1) =~ /[0-7]/ && ($j+2) =~ /[0-7]/ ) {delete${($i-1)}{($j+2)}; @a=%{($i-1)} ; print "@a\n"; }
elsif (($i-1) =~ /[0-7]/ && ($j-2) =~ /[0-7]/ ) {delete${($i-1)}{($j-2)}; @a=%{($i-1)} ; print "@a\n"; }
elsif (($i+2) =~ /[0-7]/ && ($j+1) =~ /[0-7]/ ) {delete${($i+2)}{($j+1)}; @a=%{($i+2)} ; print "@a\n"; }
elsif (($i+2) =~ /[0-7]/ && ($j-1) =~ /[0-7]/ ) {delete${($i+2)}{($j-1)}; @a=%{($i+2)} ; print "@a\n"; }
elsif (($i-2) =~ /[0-7]/ && ($j+1) =~ /[0-7]/ ) {delete${($i-2)}{($j+1)}; @a=%{($i-2)} ; print "@a\n"; }
elsif (($i-2) =~ /[0-7]/ && ($j-1) =~ /[0-7]/ ) {delete${($i-1)}{($j-1)}; @a=%{($i-1)} ; print "@a\n"; }
else { print "not match, the scripte will exit\n"; exit ; } }


先整8个关联数组,每个数组元素代表一个格,其实只要key和关联数组名就行了,元素可以任意设。
产生随机数$i and $j 代表马的走步。
$i+1,$j+2
$i+1,$j-2
$i-1,$j+2
$i-1,$j-2
$i+2,$j+1
$i+2,$j-1
$i-2,$j+1
$i-2,$j-1
这表示马的8种走法,后面的[0-7]限制了它永远走在棋盘内。
if {} elsif{} elsif {}.........决定了要是第一种情况不行,就第二种,要不就下一种,以此类推。。这样马就能自动走到下一格(走到哪一格我们并不需要关心它)。
后面的delete ${}{}是删除马走到的一格元素。就这样,有64步棋,把8个关联数组全清空为止。
举个例子:产生了随机数$i ==3.$j==3.
---->;$i+1,$j+2,now,$i==4,$j==5,
---->;$i+1,$j+2,now, $i==5,$j==7
---->;$i+1,$j-2,now, $i==6,$j==5 #第一种情况不行了,自动选择第二种。
---->;$i+1,$j-2,now, $i==7,$j==3 #第二种。
---->;$i-1,$j+2,now, $i==6,$j==5 #第一和第二种都不行了。选择第三种。
就这样自动选择,直到所有的关联数组为空就行了。

问题是,为什么不能把元素删去,觉得道理是对的。。。。
请大家给我释疑!!
这样会好些。。

#!/usr/bin/perl -w
%0=( 0,"00", 1,"01", 2,"02", 3,"03", 4,"04", 5,"05", 6,"06", 7,"07" );
%1=( 0,"10", 1,"11", 2,"12", 3,"13", 4,"14", 5,"15", 6,"16", 7,"17" );
%2=( 0,"20", 1,"21", 2,"22", 3,"23", 4,"24", 5,"25", 6,"26", 7,"27" );
%3=( 0,"30", 1,"31", 2,"32", 3,"33", 4,"34", 5,"35", 6,"36", 7,"37" );
%4=( 0,"40", 1,"41", 2,"42", 3,"43", 4,"44", 5,"45", 6,"46", 7,"47" );
%5=( 0,"50", 1,"51", 2,"52", 3,"53", 4,"54", 5,"55", 6,"56", 7,"57" );
%6=( 0,"60", 1,"61", 2,"62", 3,"63", 4,"64", 5,"65", 6,"66", 7,"67" );
%7=( 0,"70", 1,"71", 2,"72", 3,"73", 4,"74", 5,"75", 6,"76", 7,"77" );
srand; $i=int(rand( 8 )) ; $j=int(rand( 8 )) ;delete${$i}{$j}; print "$i $j \n";
for ($count=1;$count<=63;$count++) {
if ( keys(%0) == NULL && keys(%1) == NULL && keys(%2) == NULL && keys(%3) == NULL && keys(%4) ==
NULL && keys(%5) == NULL && keys(%6) == NULL && keys(%7) == NULL ) { print "the all array alreay
NULL ,EXIT\n"; exit }else {
if    (($i+1) =~ /[0-7]/ && ($j+2) =~ /[0-7]/ ) {$i +=1; $j +=2; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i+1) =~ /[0-7]/ && ($j-2) =~ /[0-7]/ ) {$i +=1; $j -=2; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i-1) =~ /[0-7]/ && ($j+2) =~ /[0-7]/ ) {$i -=1; $j +=2; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i-1) =~ /[0-7]/ && ($j-2) =~ /[0-7]/ ) {$i -=1; $j -=2; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i+2) =~ /[0-7]/ && ($j+1) =~ /[0-7]/ ) {$i +=2; $j +=1; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i+2) =~ /[0-7]/ && ($j-1) =~ /[0-7]/ ) {$i +=2; $j -=1; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i-2) =~ /[0-7]/ && ($j+1) =~ /[0-7]/ ) {$i -=2; $j +=1; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
elsif (($i-2) =~ /[0-7]/ && ($j-1) =~ /[0-7]/ ) {$i -=2; $j -=1; delete${$i}{$j}; @a=keys(%{$i})
; @a=sort(@a); print "@a                         \$i\=$i    \$j\=$j\n"; }
else { print "not match, the scripte will exit\n"; exit ; } } }
谢谢connect 兄,大家快帮帮呀。。。。
devel ....