{
本文结合几个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原创 转载请注明出处