黑白棋游戏 (codevs 2743)题解

【问题描述】

     黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。

【样例输入】

    1111

    0000

    1110

    0010

    1010

    0101

    1010

    0101

【样例输出】  

    4

    1222

    1424

    3242

    4344

【解题思路】

     看到最少步数,果断广搜。不过状态太多,需要判重。大家可以看到,出题人在数据一栏写了必须用状态压缩,不能用康托展开和hash,他说往东走,咱们偏往西走,就用hash优化。(别想从我嘴里套出我不会状态压缩和康托展开)不过hash函数会很不好找,这里我用的是二进制转十进制的方法存hash,这样的话保证每种状态下只有一个hash函数,就不需要挂链表了,主要的是比较目前状态与目标状态是否相同时会耗费点时间,不过1s还是能过的,然后一个关键的地方就是存储哪两个坐标换了位置,我是用的字符来存的,详见代码。

【代码实现】

  1 type arr=array[1..5,1..5] of char;

  2      rec=record

  3      m:arr;

  4      step:longint;

  5      ans:array[1..100,1..5] of char;

  6 end;

  7 const dx:array[1..4] of longint=(1,-1,0,0);

  8       dy:array[1..4] of longint=(0,0,-1,1);

  9 var start,ans:rec;

 10     f:array[0..200000] of boolean;

 11     spos,epos:arr;

 12     fr,r,i,j:longint;

 13     a:array[1..200000] of rec;

 14 function equal(m:arr):boolean;

 15 var i,j:longint;

 16 begin

 17  for i:=1 to 4 do

 18   for j:=1 to 4 do

 19    if m[i,j]<>epos[i,j] then exit(false);

 20  exit(true);

 21 end;

 22 function hash(m:arr):longint;//二进制转十进制,用位运算,效率高

 23 var res,i,j:longint;

 24 begin

 25  res:=0;

 26  for i:=1 to 4 do

 27   for j:=1 to 4 do

 28    begin

 29     res:=(res shl 1);

 30     res:=res+ord(m[i,j])-ord('0');

 31    end;

 32  exit(res);

 33 end;

 34 procedure bfs;

 35 var t,i,j,k,x,y:longint;

 36     now,next:rec;

 37     temp:char;

 38 begin

 39  fillchar(f,sizeof(f),true);

 40  t:=hash(spos);

 41  f[t]:=false;

 42  fr:=0;r:=1;

 43  while fr<>r do

 44   begin

 45    inc(fr);

 46    now:=a[fr];

 47    if equal(now.m) then

 48     begin

 49      ans:=now;

 50      exit;

 51     end;

 52    for i:=1 to 4 do

 53     for j:=1 to 4 do

 54      for k:=1 to 4 do

 55       begin

 56        next:=now;

 57        inc(next.step);

 58        x:=i+dx[k];

 59        y:=j+dy[k];

 60        if (x>=1)and(x<=4)and(y>=1)and(y<=4) then

 61         begin

 62          temp:=next.m[i,j];

 63          next.m[i,j]:=next.m[x,y];

 64          next.m[x,y]:=temp;

 65          next.ans[next.step,1]:=chr(ord('0')+i);

 66          next.ans[next.step,2]:=chr(ord('0')+j);

 67          next.ans[next.step,3]:=chr(ord('0')+x);

 68          next.ans[next.step,4]:=chr(ord('0')+y);

 69          next.ans[next.step,5]:=#0;//存储哪两个坐标换了位置

 70          if equal(next.m) then

 71           begin

 72            ans:=next;

 73            exit;

 74           end;

 75          t:=hash(next.m);

 76          if f[t] then

 77           begin

 78            f[t]:=false;

 79            inc(r);

 80            a[r]:=next;

 81           end;

 82         end;

 83       end;

 84    end;

 85 end;

 86 begin

 87  for i:=1 to 4 do

 88   begin

 89    for j:=1 to 4 do

 90     read(spos[i,j]);

 91    readln;

 92   end;

 93  for i:=1 to 4 do

 94   begin

 95    for j:=1 to 4 do

 96     read(epos[i,j]);

 97    readln;

 98   end;

 99  for i:=1 to 4 do

100   for j:=1 to 4 do

101    start.m[i,j]:=spos[i,j];

102  start.step:=0;

103  a[1]:=start;

104  bfs;

105  writeln(ans.step);

106  for i:=1 to ans.step do

107   begin

108    for j:=1 to 4 do

109     write(ans.ans[i,j]);

110    writeln;

111   end;

112 end.

 

你可能感兴趣的:(code)