[Drops 十滴水] 强大的搜索(中)

{

我们用BFS解决了华容道

事实上也有比较难搜的puzzle

比如十滴水 Drops

我们需要选用其他方法

}

十滴水是一个相当简约耐玩的小游戏

建议写程序之前好好玩玩

争取发现一个牛B的启发函数

(至少我没找到好的 只能裸搜之 有了牛B的启发函数会很爽 下面会提到)

[Drops 十滴水] 强大的搜索(中)

状态空间相当巨大

如果把加入一滴水算作一步

每个状态可以生成36种子状态

  当dep=4时 节点数是160w

  当dep=5时 节点数是6000w

  当dep=6时 节点数是20000w

BFS不能承受(自然的 A*更没希望)

DFS也不适合(要求最优解)

我们选用迭代加深搜索(Iterative Deepening ) 简称ID算法

迭代加深搜索兼有BFS与DFS的优点

基本的思想就是给dfs限定深度 每次只搜到选定深度

将选定深度从1-maxdep枚举一遍 每次都dfs一次即可

空间消耗很小 就是DFS的空间消耗 不会像BFS一样爆空间

也能像BFS一样 一层一层搜索 不会像DFS一样死钻一个子树

不过每次都要从头开始DFS 似乎会浪费时间

由于搜索量是指数级的 其实每次DFS开始 之前的DFS的搜索量不算什么的
 

其实就是乘了个常数而已 而且这个常数不大于2

当然ID算法也可以和A*算法结合 就是IDA*算法

关键就是设计一个好的启发函数 可惜我没设计好 就采用了裸的ID算法 效率可能不高
 

接下来讲讲我这不怎么样的迭代加深搜索

确定好了搜索的方法之后 我们就要考虑搜索的具体需求了

首先是如何表示一个状态

  由于是ID算法 我们不需要节约空间

  用6*6的矩阵存下即可

  元素就是0-4的数 代表泡泡的大小

其次是如何判断得到解

  很简单 循环判断是否全都是0

比较麻烦的就是生成子状态
 

  对于当前状态 枚举到要对(i,j)泡泡加入一滴水

  如果

    加入后小于等于4 就不用继续讨论了 直接得到一个状态

    否则这点水就爆裂了 产生4个向4个方向的小水滴 匀速直线运动

      然后就得处理这种情况 因为爆裂一个会带来连锁

      我用一张表x[] y[] d[] p[]来存储所有飞溅的小水滴

      具体操作就是一遍一遍的扫描这个表 直到不能更新为止

        x[] y[]记录坐标 d[]记录方向

        p[]是用来记录当前水滴是否还存在 因为水滴撞墙或是撞到另一个大水泡就会消失

        每撞开一个大水泡就要把生成的水滴加到表里

        每次扫描就相当于过了1单位时间 水滴同时移动了一步 这样保证了同步性

        为了保证绝对同步 刚爆开的水滴在本次扫描中不能移动

      如果水滴全没了即p[]全是1 循环停止

        需要注意以下几点

          半格半格移动水滴

            因为判断撞到泡泡是根据是否走到泡泡的所在格的边界判断的

            而每个水滴又是从格子中间开始的

           2个水滴同时撞到一个泡泡就会同时消失 不管泡泡是多大 我用f[]数组处理的

  扫描完毕就得到了新的状态 按照一般DFS的步骤即可

输入输出 用上图为例

输入 Drops.in

0 2 1 2 1 1
3 4 3 3 3 1
3 4 2 0 4 0
3 3 1 0 2 3
2 3 1 2 2 3
0 4 0 2 0 4

输出 Drops.out

2 4
0 2 1 2 1 1
3 4 3 4 3 1
3 4 2 0 4 0
3 3 1 0 2 3
2 3 1 2 2 3
0 4 0 2 0 4

2 4
0 2 1 3 1 1
3 4 4 0 4 1
3 4 2 0 4 0
3 3 1 0 2 3
2 3 1 3 2 3
0 4 0 2 0 4

[Drops 十滴水] 强大的搜索(中)
3 5
0 0 4 3 2 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 3 0 4 4
4 0 2 3 2 3
0 0 0 3 0 4

[Drops 十滴水] 强大的搜索(中)
4 5
0 0 0 4 3 3
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
4 0 4 3 3 4
0 0 0 3 0 4

[Drops 十滴水] 强大的搜索(中)
5 3

[Drops 十滴水] 强大的搜索(中)

我用我的程序刷Drops2 刷满了一试管的水

嘿嘿[Drops 十滴水] 强大的搜索(中)

看来ID算法还是不错的

不过相应的步数达到6步使用的时间就达到1秒了 7步以上出解就困难了

希望有牛人能告诉我一个牛B的启发函数哦

代码~

 

  
    
1 const m = 20 ;
2 dx: array [ 1 .. 4 ] of longint = ( 1 , 0 , - 1 , 0 );
3 dy: array [ 1 .. 4 ] of longint = ( 0 , 1 , 0 , - 1 );
4   var ansx,ansy: array [ 1 ..m] of longint;
5 ansc: array [ 1 ..m, 1 .. 6 , 1 .. 6 ] of longint;
6 x,y,d,p: array [ 1 .. 1000 ] of longint;
7 c: array [ 1 .. 6 , 1 .. 6 ] of longint;
8 bool,flag:boolean;
9 i,j,n:longint;
10 function h:longint;
11 var i,j,k,t:longint;
12 begin
13 t: = 0 ;
14 for i: = 1 to 6 do
15 begin
16 k: = 0 ;
17 for j: = 1 to 6 do
18 if c[i,j] > 0
19 then begin
20 inc(k);
21 t: = t + 5 - c[i,j];
22 end ;
23 if k > 1 then t: = t - k - k + 3 ;
24 end ;
25 for j: = 1 to 6 do
26 begin
27 k: = 0 ;
28 for i: = 1 to 6 do
29 if c[i,j] > 0 then inc(k);
30 if k > 1 then t: = t - k - k + 3 ;
31 end ;
32 if t < 0 then h: = 0 else h: = t;
33 end ;
34 procedure dfs(dep:longint);
35 var i,j,k,l,o,t,tt,tx,ty:longint;
36 b,f: array [ 1 .. 6 , 1 .. 6 ] of longint;
37 flag,bool:boolean;
38 begin
39 t: = 1 ; // t: = h;
40 if dep + t - 1 > n then exit;
41 for i: = 1 to 6 do
42 for j: = 1 to 6 do
43 if c[i,j] > 2 then begin
44 move(c,b,sizeof(b));
45 inc(c[i,j]);
46 if c[i,j] = 5
47 then begin
48 c[i,j]: = 0 ;
49 tt: = 0 ;
50 for k: = 1 to 4 do
51 begin
52 inc(tt);
53 x[tt]: = 2 * i - 1 ; y[tt]: = 2 * j - 1 ;
54 d[tt]: = k; p[tt]: = 0 ;
55 end ;
56 flag: = true;
57 while flag do
58 begin
59 t: = tt;
60 bool: = true;
61 fillchar(f,sizeof(f), 0 );
62 for k: = 1 to t do
63 if p[k] = 0 then begin
64 bool: = false;
65 x[k]: = x[k] + dx[d[k]];
66 y[k]: = y[k] + dy[d[k]];
67 if (x[k] <= 0 ) or (x[k] >= 12 ) or (y[k] <= 0 ) or (y[k] >= 12 )
68 then begin
69 p[k]: = 1 ;
70 continue;
71 end ;
72 if (odd(x[k])xor(odd(y[k])))
73 then begin
74 tx: = x[k] + dx[d[k]] + 1 ;
75 ty: = y[k] + dy[d[k]] + 1 ;
76 if c[tx shr 1 ,ty shr 1 ] > 0
77 then begin
78 f[tx shr 1 ,ty shr 1 ]: = 1 ;
79 p[k]: = 1 ;
80 inc(c[tx shr 1 ,ty shr 1 ]);
81 if c[tx shr 1 ,ty shr 1 ] = 5
82 then begin
83 c[tx shr 1 ,ty shr 1 ]: = 0 ;
84 for l: = 1 to 4 do
85 begin
86 inc(tt);
87 x[tt]: = tx - 1 ; y[tt]: = ty - 1 ;
88 d[tt]: = l; p[tt]: = 0 ;
89 end ;
90 end ;
91 end
92 else if f[tx shr 1 ,ty shr 1 ] = 1
93 then p[k]: = 1 ;
94 end ;
95 end ;
96 flag: = not bool;
97 end ;
98 end ;
99 flag: = true;
100 for k: = 1 to 6 do
101 for l: = 1 to 6 do
102 flag: = flag and (c[k,l] = 0 );
103 if flag
104 then begin
105 for k: = 1 to dep - 1 do
106 begin
107 writeln(ansx[k], ' ' ,ansy[k]);
108 for l: = 1 to 6 do
109 begin
110 for o: = 1 to 5 do
111 write(ansc[k,l,o], ' ' );
112 writeln(ansc[k,l, 6 ]);
113 end ;
114 end ;
115 writeln(i, ' ' ,j);
116 close(input); close(output);
117 halt;
118 end ;
119 ansx[dep]: = i; ansy[dep]: = j;
120 move(c,ansc[dep],sizeof(c));
121 dfs(dep + 1 );
122 move(b,c,sizeof(b));
123 end ;
124 end ;
125 begin
126 assign(input, ' drop.in ' ); reset(input);
127 assign(output, ' drop.out ' ); rewrite(output);
128 { randomize;
129 if random(9999)=0
130 then begin
131 writeln('WARNING:LOW LOW RP...');
132 writeln('Tips:Please do not zhuang B');
133 close(input); close(output);
134 halt;
135 end; }
136 for i: = 1 to 6 do
137 for j: = 1 to 6 do
138 read(c[i,j]);
139 n: = 0 ;
140 while n < m do
141 begin
142 inc(n);
143 dfs( 1 );
144 end ;
145 writeln( ' WARNING:LOW LOW RP... ' );
146 writeln( ' Tips:Please do not zhuang B ' );
147 close(input); close(output);
148 end .
149

 

下一篇介绍一个比较麻烦的游戏 bloxorz

极力推荐!

我用的算法么 下次说

 

BOB HAN原创 转载请注明出处

你可能感兴趣的:(drop)