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

{

我们用BFS解决了华容道

事实上也有比较难搜的puzzle

比如十滴水 Drops

我们需要选用其他方法

}

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

建议写程序之前好好玩玩

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

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

状态空间相当巨大

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

每个状态可以生成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


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


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


5 3

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

嘿嘿

看来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原创 转载请注明出处

posted on 2010-09-16 23:30  Master_Chivu  阅读(5303)  评论(15编辑  收藏  举报

导航