回溯算法解决智能拼图的最小步骤的问题

本文介绍了如何运用回溯算法解决智能拼图的最小步骤问题。在不能标记走过位置的情况下,通过保存整个拼图状态,利用递归方式找出0号位置在不同方向上的移动所达到的最小步数。文章提供了代码实现,并邀请读者留言讨论。
摘要由CSDN通过智能技术生成

题目描述

要求输入一个拼图的初始状态,返回拼图的成功所经过的最小的步数,例如:

初始状态:
1 2 3
4 5 6
7 0 8
成功的状态
1 2 3
4 5 6
7 8 0

输出步数 : 1

0号可以与相邻的数字进行交换,要求最后的状态0号位于右下方,其余位置按上面的顺序排列

分析

这和我们常见的迷宫求解的题目有些差别,迷宫求解的过程中可以标记走过的路,以防止重复同样的步骤,但这里不能通过标记走过的位置了,因为一个要达到最终的状态,可能一个位置要重复地走很多遍才能达到成功的状态。
虽然不能标记拼图中单独的位置,我们可以把整个地图的状态保存下来,当0位置改变的时候,我们判断改变后的拼图是否已经出现过,如果出现过,0位置不改变,否则才改变。
在这里插入图片描述
这里我们采用递归的分析方式,函数findCount(x,y)返回当0位于(x,y)位置时到达成功状态所经过的最小的步数,每次0号位置都有四种移动方案 向上、向下、向左、向右,只要统计出经过四个方向到达成功状态的最小步数,
转换成代码就是

findCount(x,y) = min(findCount(x-1,y),findCount(x,y-1)
						, findCount(x+1,y),findCount(x,y+1));

只要找到递归的公式,递归的代码比较容易了。

这里还有一个问题就是怎样保存整个拼图,这个方法有很多,我用了一种hash的方式

	//传入保存拼图的数组
    int fun(vector<vector<int> > &vec)
    {
   
        int tmp = 0;
        int row = vec.size();
        for(int i = 0; i < row; ++i)
        {
   
            int col = vec[i].size();
            for(int j = 0; j < col; ++j)
            {
   
                int a = vec[i][j] + (i*row+j);
                //求解拼图中各个位加上一定的对应的数值后,再向右移动相应的位数,
                //这里要尽量保证不同的拼图状态求出的hash 值不相同
                tmp += (a << (i*row+j));
            }
        }
        return tmp;
    }

代码的完整实现

#include <iostream>
#include <queue>
#include <vector>
#i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值