八数码难题 (codevs 1225)题解

【问题描述】

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

【样例输入】

    283104765

【样例输出】

     4

【解题思路】

     这题要求最少步数,因此为广度优先搜索,用队列实现。最简单的方法就是直接将每种状态存入3×3的数组中,然后将空格往四个方向移动,直至目标状态。

    不过,让我们来看一看样例。

    按往常来说,如果是存入3×3的数组中,那么样例中应该是  2 8 3      

                                                                             1 0 4

                                                                             7 6 5 

    可是,样例却是一串数字,且中间没有空格,那么,这就给了我们一种思路,以字符串的形式存入,然后搜索,与目标状态比较时也方便一些。那么我们就换成字符串来搜索,但是字符串中要注意一下,第三位不能移到第四位,第四位不能移到第三位,因此,我们需要对该数字进行判断,看它属于哪一列,然后再搜索。

    不过,这两种方式都会超时(在输出结果的步数比较大的时候),因此,我们需要判重,然而,直接开一个12345678-876543210的布尔型数组会超时,所以,这里我们用到了哈希优化。

【代码实现】

  1 type rec=record

  2      s:string;

  3      s1,dep:longint;

  4 end;

  5 const di:array[1..4] of longint=(-1,-3,3,1);

  6       c:string='123804765';

  7 var a:array[1..100000] of rec;

  8     b:string;

  9     f,r,i,j,k,x:longint;

 10     flag:array[1..1000010] of boolean;

 11 procedure bfs;

 12 var si:char;

 13     i,j,k:longint;

 14 begin

 15  while f<r do

 16   begin

 17    inc(f);

 18    case a[f].s1 of//判断数字属于哪一列

 19     2,5,8:

 20      for i:=1 to 4 do

 21       if (a[f].s1+di[i]>=1)and(a[f].s1+di[i]<=9) then

 22        begin

 23         inc(r);

 24         a[r]:=a[f];

 25         a[r].s[a[r].s1]:=a[r].s[a[r].s1+di[i]];

 26         a[r].s[a[r].s1+di[i]]:='0';

 27         a[r].s1:=a[r].s1+di[i];

 28         inc(a[r].dep);

 29         val(a[r].s,x);

 30         if not(flag[x mod 1000009]) then

 31          dec(r)

 32         else

 33          begin

 34           flag[x mod 1000009]:=false;

 35           if a[r].s=c then

 36            begin

 37             writeln(a[r].dep);

 38             halt;

 39            end;

 40          end;

 41        end;

 42     1,4,7:

 43      for i:=2 to 4 do

 44       if (a[f].s1+di[i]>=1)and(a[f].s1+di[i]<=9) then

 45        begin

 46         inc(r);

 47         a[r]:=a[f];

 48         a[r].s[a[r].s1]:=a[r].s[a[r].s1+di[i]];

 49         a[r].s[a[r].s1+di[i]]:='0';

 50         a[r].s1:=a[r].s1+di[i];

 51         inc(a[r].dep);

 52         val(a[r].s,x);

 53         if not(flag[x mod 1000009]) then

 54          dec(r)

 55         else

 56          begin

 57           flag[x mod 1000009]:=false;

 58           if a[r].s=c then

 59            begin

 60             writeln(a[r].dep);

 61             halt;

 62            end;

 63          end;

 64        end;

 65     3,6,9:

 66      for i:=1 to 3 do

 67       if (a[f].s1+di[i]>=1)and(a[f].s1+di[i]<=9) then

 68        begin

 69         inc(r);

 70         a[r]:=a[f];

 71         a[r].s[a[r].s1]:=a[r].s[a[r].s1+di[i]];

 72         a[r].s[a[r].s1+di[i]]:='0';

 73         a[r].s1:=a[r].s1+di[i];

 74         inc(a[r].dep);

 75         val(a[r].s,x);

 76         if not(flag[x mod 1000009]) then

 77          dec(r)

 78         else

 79          begin

 80           flag[x mod 1000009]:=false;

 81           if a[r].s=c then

 82            begin

 83             writeln(a[r].dep);

 84             halt;

 85            end;

 86          end;

 87        end;

 88     end;

 89   end;

 90 end;

 91 begin

 92  fillchar(flag,sizeof(flag),true);

 93  readln(a[1].s);

 94  for i:=1 to 9 do

 95   if a[1].s[i]='0' then

 96    begin

 97     a[1].s1:=i;

 98     break;

 99    end;

100  f:=0;r:=1;

101  bfs;

102 end.

 

你可能感兴趣的:(code)