消消乐实验总结与反思

问题重述

背景介绍:
《开心消消乐》是一款乐元素研发的三消类休闲游戏。游戏中消除的对象为小动物的头像,包括小浣熊、小狐狸、小青蛙和小鸡等动物头像。玩家通过移动动物头像位置凑够同行/同列3个或3个以上即可消除。

现在定义消消乐规则如下:
1.游戏中共允许K种对象,分布在大小为M×N的格子布局中。
2.交换两个对象位置,凑够3个或3个以上即可消除,被消除的空格由正上方对象掉落填充。
3.可能出现三种消除方式: 同行(列)三个、同行(列)四个、同行(列)五个。分别 得分1分、4分、10分。
4.当没有可通过交换消除的对象时,游戏终止。

回溯法 [ Back Tracking Method ]
(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。(取自百度百科)

回溯法解题的关键要素
确定了问题的解空间结构后,回溯法将从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。开始结点成为活结点,同时也成为扩展结点。在当前的扩展结点处,向纵深方向搜索并移至一个新结点,这个新结点就成为一个新的活结点,并成为当前的扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。此时应往回移动(回溯)至最近的一个活结点处,并使其成为当前的扩展结点。回溯法以上述工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已无活结点时为止。

运用回溯法解题的关键要素有以下三点:
(1) 针对给定的问题,定义问题的解空间
(2) 确定易于搜索的解空间结构;
(3) 以深度优先方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。

递归和迭代回溯
一般情况下可以用递归函数实现回溯法,递归函数模板如下:

void BackTrace(int t) {
	if(t>n)
		Output(x);
	else
		for(int i = f (n, t); i <= g (n, t); i++ ) {
			x[t] = h(i);
			if(Constraint(t) && Bound (t))
				BackTrace(t+1);
		}
}

其中,t 表示递归深度,即当前扩展结点在解空间树中的深度;n 用来控制递归深度,即解空间树的高度。当 t>n时,算法已搜索到一个叶子结点,此时由函数Output(x)对得到的可行解x进行记录或输出处理。用 f(n, t)和 g(n, t)分别表示在当前扩展结点处未搜索过的子树的起始编号和终止编号;h(i)表示在当前扩展结点处x[t] 的第i个可选值;函数 Constraint(t)和 Bound(t)分别表示当前扩展结点处的约束函数和限界函数。若函数 Constraint(t)的返回值为真,则表示当前扩展结点处x[1:t] 的取值满足问题的约束条件;否则不满足问题的约束条件。若函数Bound(t)的返回值为真,则表示在当前扩展结点处x[1:t] 的取值尚未使目标函数越界,还需由BackTrace(t+1)对其相应的子树做进一步地搜索;否则,在当前扩展结点处x[1:t]的取值已使目标函数越界,可剪去相应的子树。

采用迭代的方式也可实现回溯算法,迭代回溯算法的模板如下:

void IterativeBackTrace(void) {
	int t = 1;
	while(t>0) {
		if(f(n, t) <= g( n, t))
			for(int i = f(n, t); i <= g(n, t); i++ ) {
				x[t] = h(i);
				if(Constraint(t) && Bound(t)) {
					if ( Solution(t))
						Output(x);
					else
						t++;
				}
			}
		else 
			t− −;
	}
}

在上述迭代算法中,用Solution(t)判断在当前扩展结点处是否已得到问题的一个可行解,若其返回值为真,则表示在当前扩展结点处x[1:t] 是问题的一个可行解;否则表示在当前扩展结点处x[1:t]只是问题的一个部分解,还需要向纵深方向继续搜索。

用回溯法解题的一个显著特征是问题的解空间是在搜索过程中动态生成的,在任何时刻算法只保存从根结点到当前扩展结点的路径。如果在解空间树中,从根结点到叶子结点的最长路径长度为 h(n),则回溯法所需的计算空间复杂度为 O(h(n)),而显式地存储整个解空间复杂度则需要O(2h(n))或O(h(n)!)。

数据结构
个人推荐map,简单点数组就行,用堆栈也是OK的。

算法步骤

  1. 每次递归都找出那个时候矩阵的所有可交换点,进行每个点的深度搜索
  2. 递归结束条件有两个
    ①没有可交换点,回溯;
    ②剪枝,查看map是否有相同状态但分数更高的,如果有更高的,结束递归进行回溯;
    否则,替换掉分数低的进行下一步递归;
  3. 判断顶点周围是否存在可以消去的条件;可以通过判断整行或者整列可否消去;
  4. 每次消去之后正上方的方块会掉下来;
  5. 掉下来之后还要多一次判断是否可以自动再消,直到确认不能再消。即每次消除+掉落为一个过程,完成一次之后就需要判断。没有->继续搜索判断;有->继续消去+下移;
  6. 进入下一次递归之前要把当前状态记录到map上。

猜你喜欢

转载自blog.csdn.net/Xindolia_Ring/article/details/83832319
今日推荐