骑士精神(BZOJ1085) 题解
【问题描述】
在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务。
【样例输入】
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
【样例输出】
7
-1
【解题思路】
这题为SCOI2005的题,首先看到这一题,以为是广搜,结果发现搜索树太大了,用队列会炸,于是想到了迭代加深。
把答案作为加深的对象,不断的对答案+1,然后我们可以利用估价函数减小搜索的范围,其实就打一个深搜出来就行了。
【代码实现】
1 const en:array[1..5] of string=('11111','01111','00*11','00001','00000'); 2 dx:array[1..8] of longint=(2,-2,1,1,-1,-1,2,-2); 3 dy:array[1..8] of longint=(1,1,-2,2,-2,2,-1,-1); 4 var a:array [1..5] of string[5]; 5 h,r,i,n,j,w,ans,mini,x,y:longint; 6 procedure swap(var x,y:char); 7 var ch:char; 8 begin 9 ch:=x; 10 x:=y; 11 y:=ch; 12 end; 13 procedure dfs(x,y,dep,last:longint); 14 var i,j,d,xx,yy:longint; 15 begin 16 d:=0; 17 if mini<>-1 then 18 exit; 19 for i:=1 to 5 do 20 for j:=1 to 5 do 21 if a[i,j]<>en[i,j] then 22 inc(d); 23 if d=0 then 24 begin 25 mini:=dep; 26 exit; 27 end; 28 if ans-dep<d-1 then 29 exit; 30 for i:=1 to 8 do 31 begin 32 if mini<>-1 then 33 break; 34 if i=9-last then 35 continue; 36 xx:=x+dx[i]; 37 yy:=y+dy[i]; 38 if (xx in[1..5])and(yy in[1..5]) then 39 begin 40 swap(a[x,y],a[xx,yy]); 41 dfs(xx,yy,dep+1,i); 42 swap(a[x,y],a[xx,yy]); 43 end; 44 end; 45 end; 46 begin 47 readln(w); 48 while w>0 do 49 begin 50 a[1]:='';a[2]:='';a[3]:='';a[4]:='';a[5]:=''; 51 dec(w); 52 for i:=1 to 5 do 53 begin 54 readln(a[i]); 55 for j:=1 to 5 do 56 if a[i,j]='*' then 57 begin 58 x:=i; 59 y:=j; 60 end; 61 end; 62 mini:=-1; 63 for ans:=0 to 15 do 64 begin 65 dfs(x,y,0,-1); 66 if mini<>-1 then 67 break; 68 end; 69 if mini=-1 then 70 writeln(mini) 71 else 72 writeln(ans); 73 end; 74 end.