滑动积木块问题——A*算法

本文介绍了使用A*算法解决滑动积木块问题的方法。通过建立优先队列、节点存储、格局映射等数据结构,实现了算法的高效运行。文章详细阐述了算法流程,包括格局的表示、评估函数的计算以及关键细节的优化,如使用Zobrist值减少时间复杂度。同时,证明了在滑动积木块问题中,将isOpen和isClose表结合成一个map的正确性和效率。最后,验证了算法的单调性限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于规则:

初始格局(黑黑黑白白白空),最终格局(白白白黑黑黑空),每次可以将滑块移入相邻空格,也可以跳过最多两个其他滑块进入空格。

耗散值gn的计算:移入相邻空格gn=gn+1;跳过m个其他滑块进入空格gn=gn+m。

评估值hn的计算:每个白块前黑块的数目之和,如初始格局hn为9,最终格局hn为0。

 

关于算法:

1. 在描述算法之前,首先阐述几个本程序中几个比较重要的“容器”。

①优先队列(PriorityQueue):即为此问题中的open表,用于存放已存在但还未扩展的节点。重写Comparator,使耗散值gn+评估值hn较小的排在队首。

②节点(Status):用于存放节点,其成员变量father执行了close表的功能。

③键值对(Map<Long, Integer>):存储“格局-gn”映射,执行isOpen表和isClose的功能(isOpen表和isClose表分别为open表和close表的判重表)。格局用一个hash值来唯一表示。

此处hash值选用的的是Zobrist值,Zobrist值的产生方法:https://blog.csdn.net/aqzwss/article/details/52850737

2. 算法描述:主要思路为“出队-扩展-判定入队还是舍弃-出队”循环

①取优先队列队首元素。

②取出空格位置empty,对于empty-3到empty+3范围内的每一格j,若j未越界且不为空格,则进行尝试移动,并生成新节点。

③对于新节点a,若在map中能查到此格局,且a.gn小于map中记录的gn,则将a入队,更新map;若a.gn大于等于map中的gn或在map中查不到该格局,则舍弃该节点(这里融合了对open表判重和close表的判重,后面有详细解释)。

④回到①,不断循环,直至取出的节点格局为目标格局位置。

 

关于一些细节的处理:

1. status存储使用byte[],节省内存。

2. 评估值hn的计算用一层循环替换两层循环,减小时间复杂度。

3. 键值对内存储的是<格局对应zobrist值,gn>,经过分析,此处使用zobrist值来唯一表示一个格局并进行相关操作在时间上会明显快于其他表示方式。

4. 本程序中并未使用分开的isOpen表和isClose表来对open表和close表进行分别判重,而是将isClose表和isOpen表结合成一个map,对于滑动积木块问题,此方法证明无误,而且可以省去一些操作。感兴趣的可以看下面详解(isOpen表和isClose表分别为open表和close表的判重表)。

5. 关于单调性限制的证明也会在最后附上。

6. 下面先附上代码。

 

public class Status {	
	
	public static byte SIZE;
	private byte status[] = new byte[SIZE*2+1];	//当前格局	
	private int gn;		//累计路径耗散值(Dissipative value) 
	private int hn;		//评价函数(Evaluation function)
	private Status father;    //存放父节点位置 
	private int direction;    //存放移动方向
	private long zobrist;
	private int empty;
	
	public Status() {
		
	}
	
	public Status(byte[] s, int g, Status father, int direction, long zobrist){   //构造函数 
		if (s.length != SIZE*2+1)
			System.out.p
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值