蓝桥杯 历届试题-九宫重排

问题描述

  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
jgcp1jgcp2
  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

解题思路

看起来非常像一个全排列问题,但这道题不是。
首先这道题要求的状态的转换是有限制要求的,即每一次移动只能移动空格和空格的上下左右,且与他移动的还必须存在,即不能越界。其次这道题要求的是最短路径,想到这里就很明显了,把当前9个数的位置信息当成一个节点,通过移动格子能转换到的状态也就是他的邻接点,把它当成一副图用bfs来做就ok了。
不过要注意一点就是其实不需要建图,每一个状态的相邻节点都能通过空格的位置推出。
不过这道题有一个坑点,如何判断一个节点是否已经访问过,这很重要,如果没法判断,那么程序一旦碰到环就会死循环,那就建个数组标记一下,可是怎么标记啊,一个节点有9个信息,总不能用9维的数组吧。所以一个好的解决方法就是用散列表,这样问题就解决了。
程序要求最小步数,那么就在第一次访问到每一节点时标记一下从谁访问的,最后直接从终止节点开始一路推到开始节点就可以了。

代码

#include <iostream>
#include <cstring>

#define QMAX 370000

#define HASHMAX 10000

int htable[HASHMAX];

int next[QMAX];

int queue[QMAX][9];

int zeros[QMAX];

int vis[QMAX];

int front;
int r
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值