[华容道] 强大的搜索(上)

{

本文结合几个puzzle小游戏的解答

浅述几种搜索思想的具体应用

程序可能有不完善之处

请指出

第一部分 谈一下华容道的搜索

}

华容道大家应该不会陌生

游戏取材于历史 题材很好 设计得也很巧妙

我很弱 玩不过几关

就想到的用搜索来暴力

暴力也不能硬搞

先好好分析 再下手

由于这是一个具体的实际问题

先考虑用什么搜索方法

  我用的是BFS 这样方便得出最优解

  每次的选择也就2种左右 多数只有1种走法

  而且步骤最多的局面也就180+步 BFS完全可以应对

然后要考虑的就是怎么存储状态

  为了节约空间 我把一个4*5的局面压缩成一个字符串String[20]

  然后可以配合Hash表利用优秀的字符串hash函数--BKDRhash判断重复

继续是怎么生成新的节点 就是搜索的关键部分

  我们记录空白部分的位置 所有的移动必然是和空白部分相关联的

  向空白位置的四个方向探查与空白相邻的元素是哪一个

  然后分类讨论 决定怎么移动

    *如果是小兵(1*1) 直接和空白交换 得到新的状态

    *如果查到了将领(1*2 || 2*1) 不必再继续探查出将领的位置

    我的做法是探查另一个空白的四周 来决定是否可以移动将领 具体需要仔细考虑 就在这里留白吧

    *如果是曹操 也是和将领一样的思路 不过代码还要简单 因为曹操是对称的(2*2)

再其次是判断是否得到解

  用数组c[]来记录曹操的左上角

  当为14时 就出解了

最后提一下 我输入输出的格式吧

我把每个元素表示为A-J的大写字母 A曹操 B-F将领 G-J小兵 K空白

例如上图就是

  FFBB

  DAAE

  DAAE

  HCCI

  JKKG

压缩成串就是FFBBDAAEDAAEHCCIJKKG

注意细节~

贴个代码呗

 

1 //Bob's Puzzle Cracker V1.00
2  {$I+,Q+,R+,S+}
3  const maxq=500000;
4 base=$FFFFF;
5 lset:set of char=['A'..'K'];
6 d:array[1..4]of longint=(-4,1,4,-1);
7 dc:array[1..4]of char=('D','L','U','R');
8 n:array['A'..'K']of longint=(1,2,2,2,2,2,3,3,3,3,4);
9  var q:array[1..maxq]of string[20];
10 hash:array[0..base]of longint;
11 b1,b2,c,tab,nxt,ansd,dep,prev:array[1..maxq]of longint;
12 ansc:array[1..maxq]of char;
13 ans0,t,tt,tt0,h,i,j,tx,ty,tz,p:longint;
14 flag,bool:boolean;
15 ch:char;
16  procedure out(x:longint);
17  begin
18  if x=0 then exit;
19 out(prev[x]);
20  if x<>1
21 then begin
22 inc(tt0);
23 writeln(tt0,' ',ansc[x],' ',dc[ansd[x]]);
24 writeln(copy(q[x],1,4));
25 writeln(copy(q[x],5,4));
26 writeln(copy(q[x],9,4));
27 writeln(copy(q[x],13,4));
28 writeln(copy(q[x],17,4));
29 writeln;
30 end;
31  end;
32  begin
33 assign(input,'puzzle.in'); reset(input);
34 assign(output,'puzzle.out'); rewrite(output);
35 while not eof do
36 begin
37 read(ch);
38 if ch in lset
39 then begin
40 inc(i);
41 q[1]:=q[1]+ch;
42 if ch='K'
43 then if b1[1]=0
44 then b1[1]:=i
45 else b2[1]:=i;
46 if (ch='A')and(c[1]=0) then c[1]:=i;
47 end;
48 end;
49 if c[1]=14
50 then begin
51 writeln(0);
52 close(input); close(output);
53 halt;
54 end;
55 ans0:=0;
56 for i:=1 to 20 do
57 ans0:=(ans0*131+n[q[1][i]])and base;
58 hash[ans0]:=1; tab[1]:=1; tt:=1;
59 h:=1; t:=1;
60 while h<=t do
61 begin
62 for i:=1 to 4 do
63 begin
64 if ((b1[h]=4)or(b1[h]=8)or(b1[h]=12)or(b1[h]=16)or(b1[h]=20))and(i=2)
65 or((b1[h]=1)or(b1[h]=5)or(b1[h]=9)or(b1[h]=13)or(b1[h]=17))and(i=4)
66 then continue;
67 tx:=b1[h]+d[i];
68 if (tx<1)or(tx>20) then continue;
69 inc(t);
70 q[t]:=q[h];
71 flag:=false;
72 case q[h][tx] of
73 'A':
74 begin
75 ty:=b1[h]+d[i]*2; tz:=b2[h]+d[i]*2;
76 if (ty<1)or(ty>20)or(tz<1)or(tz>20)
77 then begin
78 dec(t);
79 continue;
80 end;
81 if q[t][b2[h]+d[i]]='A'
82 then begin
83 q[t][ty]:='K'; q[t][tz]:='K';
84 q[t][b1[h]]:='A'; q[t][b2[h]]:='A';
85 b1[t]:=ty; b2[t]:=tz;
86 c[t]:=c[h]-d[i];
87 ansc[t]:='A';
88 flag:=true;
89 end;
90 end;
91 'B'..'F':
92 begin
93 ty:=b1[h]+d[i]*2;
94 if (ty>=1)and(ty<=20)and(q[t][ty]=q[h][tx])
95 then begin
96 q[t][ty]:='K';
97 q[t][b1[h]]:=q[h][tx];
98 b1[t]:=ty;
99 b2[t]:=b2[h];
100 ansc[t]:=q[h][tx];
101 c[t]:=c[h];
102 flag:=true;
103 end
104 else begin
105 ty:=b2[h]+d[i];
106 if (ty<1)or(ty>20)
107 then begin
108 dec(t);
109 continue;
110 end;
111 if q[t][ty]=q[h][tx]
112 then begin
113 q[t][b1[h]]:=q[h][tx]; q[t][b2[h]]:=q[h][tx];
114 q[t][tx]:='K'; q[t][ty]:='K';
115 b1[t]:=tx; b2[t]:=ty;
116 ansc[t]:=q[h][tx];
117 c[t]:=c[h];
118 flag:=true;
119 end;
120 end;
121 end;
122 'G'..'J':
123 begin
124 q[t][b1[h]]:=q[h][tx];
125 q[t][tx]:='K';
126 b1[t]:=tx;
127 b2[t]:=b2[h];
128 ansc[t]:=q[h][tx];
129 c[t]:=c[h];
130 flag:=true;
131 end;
132 end;
133 if flag
134 then begin
135 ans0:=0;
136 for j:=1 to 20 do
137 ans0:=(ans0*131+n[q[t][j]])and base;
138 p:=hash[ans0];
139 while p<>0 do
140 begin
141 bool:=true;
142 for j:=1 to 20 do
143 if n[q[tab[p]][j]]<>n[q[t][j]]
144 then begin bool:=false; break; end;
145 if bool
146 then begin
147 dec(t);
148 flag:=false;
149 break;
150 end;
151 p:=nxt[p];
152 end;
153 if flag
154 then begin
155 ansd[t]:=i;
156 prev[t]:=h;
157 dep[t]:=dep[h]+1;
158 if c[t]=14
159 then begin
160 writeln(dep[t]);
161 out(t);
162 close(input); close(output);
163 halt;
164 end;
165 inc(tt);
166 tab[tt]:=t;
167 nxt[tt]:=hash[ans0];
168 hash[ans0]:=tt;
169 end;
170 end
171 else dec(t);
172 end;
173 for i:=1 to 4 do
174 begin
175 if ((b2[h]=4)or(b2[h]=8)or(b2[h]=12)or(b2[h]=16)or(b2[h]=20))and(i=2)
176 or((b2[h]=1)or(b2[h]=5)or(b2[h]=9)or(b2[h]=13)or(b2[h]=17))and(i=4)
177 then continue;
178 tx:=b2[h]+d[i];
179 if (tx<1)or(tx>20) then continue;
180 inc(t);
181 q[t]:=q[h];
182 flag:=false;
183 case q[h][tx] of
184 'A':
185 begin
186 ty:=b2[h]+d[i]*2; tz:=b1[h]+d[i]*2;
187 if (ty<1)or(ty>20)or(tz<1)or(tz>20)
188 then begin
189 dec(t);
190 continue;
191 end;
192 if q[t][b1[h]+d[i]]='A'
193 then begin
194 q[t][ty]:='K'; q[t][tz]:='K';
195 q[t][b2[h]]:='A'; q[t][b1[h]]:='A';
196 b2[t]:=ty; b1[t]:=tz;
197 c[t]:=c[h]-d[i];
198 ansc[t]:='A';
199 flag:=true;
200 end;
201 end;
202 'B'..'F':
203 begin
204 ty:=b2[h]+d[i]*2;
205 if (ty>=1)and(ty<=20)and(q[t][ty]=q[h][tx])
206 then begin
207 q[t][ty]:='K';
208 q[t][b2[h]]:=q[h][tx];
209 b2[t]:=ty;
210 b1[t]:=b1[h];
211 ansc[t]:=q[h][tx];
212 c[t]:=c[h];
213 flag:=true;
214 end
215 else begin
216 ty:=b1[h]+d[i];
217 if (ty<1)or(ty>20)
218 then begin
219 dec(t);
220 continue;
221 end;
222 if q[t][ty]=q[h][tx]
223 then begin
224 q[t][b2[h]]:=q[h][tx]; q[t][b1[h]]:=q[h][tx];
225 q[t][tx]:='K'; q[t][ty]:='K';
226 b2[t]:=tx; b1[t]:=ty;
227 ansc[t]:=q[h][tx];
228 c[t]:=c[h];
229 flag:=true;
230 end;
231 end;
232 end;
233 'G'..'J':
234 begin
235 q[t][b2[h]]:=q[h][tx];
236 q[t][tx]:='K';
237 b2[t]:=tx;
238 b1[t]:=b1[h];
239 ansc[t]:=q[h][tx];
240 c[t]:=c[h];
241 flag:=true;
242 end;
243 end;
244 if flag
245 then begin
246 ans0:=0;
247 for j:=1 to 20 do
248 ans0:=(ans0*131+n[q[t][j]])and base;
249 p:=hash[ans0];
250 while p<>0 do
251 begin
252 bool:=true;
253 for j:=1 to 20 do
254 if n[q[tab[p]][j]]<>n[q[t][j]]
255 then begin bool:=false; break; end;
256 if bool
257 then begin
258 dec(t);
259 flag:=false;
260 break;
261 end;
262 p:=nxt[p];
263 end;
264 if flag
265 then begin
266 ansd[t]:=i;
267 prev[t]:=h;
268 dep[t]:=dep[h]+1;
269 if c[t]=14
270 then begin
271 writeln(dep[t]);
272 out(t);
273 close(input); close(output);
274 halt;
275 end;
276 inc(tt);
277 tab[tt]:=t;
278 nxt[tt]:=hash[ans0];
279 hash[ans0]:=tt;
280 end;
281 end
282 else dec(t);
283 end;
284 inc(h);
285 end;
286 writeln('No solution!');
287 close(input); close(output);
288 end.
289

 

 

 

实际问题 数据一般不会太大 这里的华容道就是一个4*5的小问题

用普通的BFS就可以解决了

不过还有一些比较繁琐 比较困难的问题

比如bloxorz十滴水等其他问题 baidu一下 就可以玩到了

都是很不错的小游戏

今后会讨论到 怎么用程序解决

 

BOB HAN原创 转载请注明出处

posted on 2010-09-15 23:00  Master_Chivu  阅读(2324)  评论(2编辑  收藏  举报

导航