P1312 Mayan游戏

本文解析了如何使用回溯法解决Mayan游戏问题,涉及消除相同方块的算法、移动操作的实现,以及深度优先搜索(DFS)的巧妙设计。通过实例展示了如何将搜索框架、约束条件和剪枝策略转化为代码,以优化游戏求解过程。
摘要由CSDN通过智能技术生成

P1312 Mayan游戏

说实话,这道题目其实我以前是做过一遍的,但是当时做的时候完全是看题解一步步打出来的qwq,毕竟大模拟放到谁身上都不想做,好了回到正题。这道题目考验的实际上是回溯法的第三个方面:如何将自己的思考转换成代码实现。
这道题目搜索框架以及约束条件都不难确定,唯一的剪枝也是非常好想的,就是当两个相邻的方块如果相等时就不去移动了。那么唯一的难点就是如何将消除以及移动这两个操作做好。
那么如何消除呢?其实可以把当前游戏界面的各个状态遍历一遍找到所需要消除的方块,具体是这样实现:

bool remove(){
	int flag=0;
	for(int i=1;i<=5;i++){
		for(int j=1;j<=7;j++){
			if(i-1>=1&&i+1<=5&&mp[i][j]==mp[i-1][j]&&mp[i+1][j]==mp[i][j]&&mp[i][j]!=0){
				del[i][j]=del[i+1][j]=del[i-1][j]=1;flag=1;
			}
			if(j-1>=1&&j+1<=7&&mp[i][j]==mp[i][j-1]&&mp[i][j+1]==mp[i][j]&&mp[i][j]!=0){
				del[i][j]=del[i][j+1]=del[i][j-1]=1;flag=1;
			}
		}
	}
	if(!flag)return false;
	if(flag){
		for(int i=1;i<=5;i++){
			for(int j=1;j<=7;j++){
				if(del[i][j]){
					del[i][j]=0;
					mp[i][j]=0;
				}
			}
		}
	}
	return true;
}

如何更新呢?实际上就是对于每一列,考虑每一列的分布情况,从最底层开始遍历到满足它的下面是空的但是本身却有方块的情况,然后开始往下找到这个方块应该被放到的位置,就会有:

void update(){
	for(int i=1;i<=5;i++){
		for(int j=1;j<=7;j++){
			if(j-1>=1&&mp[i][j-1]==0&&mp[i][j]){
				int p=j-1;
				while(mp[i][p]==0&&p>=1)p--;
				p++;
				swap(mp[i][j],mp[i][p]);
			}
		}
	}
}

最后就是dfs的设计了
dfs的状态不难考虑,就是当前的图的状态,换句话说抽象图的每一个节点都是图的状态,那么我们可以考虑用一个数组来表示之前的状态,然后回溯完毕后,将这个数组复制回原来的图中就可以了

void dfs(int k){
	if(check()){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=3;j++){
				cout<<ans[i][j]<<" ";
			}
			cout<<endl;
		}
		exit(0);
	}
	if(k>n)return;
	for(int i=1;i<=5;i++){
		for(int j=1;j<=7;j++){
			last[k][i][j]=mp[i][j];
		}
	}
	for(int i=1;i<=5;i++){
		for(int j=1;j<=7;j++){
			if(i+1<=5&&mp[i][j]&&mp[i+1][j]!=mp[i][j]){
				ans[k][1]=i-1;ans[k][2]=j-1;ans[k][3]=1;
				move(i,j,1);
				dfs(k+1);
				for(int i=1;i<=5;i++){
					for(int j=1;j<=7;j++){
						mp[i][j]=last[k][i][j];
					}
				}
				ans[k][1]=-1;ans[k][2]=-1;ans[k][3]=-1;
			}
			if(i-1>=1&&mp[i][j]&&mp[i-1][j]!=mp[i][j]){
				ans[k][1]=i-1;ans[k][2]=j-1;ans[k][3]=-1;
				move(i,j,-1);
				dfs(k+1);
				for(int i=1;i<=5;i++){
					for(int j=1;j<=7;j++){
						mp[i][j]=last[k][i][j];
					}
				}
				ans[k][1]=-1;ans[k][2]=-1;ans[k][3]=-1;
			}
		}
	}
}

然后这道题目就被完美地解决了。

小结

   这道题目的构建是遵循先框架后细节的程序设计环节,即我们大概设计好搜索的框架,然后慢慢往里面填充细节。事先想好如何实现然后逻辑清晰的展现出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值