黑白棋游戏 (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.