蓝桥杯 历届试题 九宫重排(bfs)

问题描述

  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

  输入第一行包含九宫的初态,第二行包含九宫的终态。

输出格式

  输出最少的步数,如果不存在方案,则输出-1。

样例输入

12345678.
123.46758

样例输出

3

样例输入

13524678.
46758123.

样例输出

22

 

【解题思路】

这道题用了bfs+康拓判重

bfs既广度优先搜索,搜到的第一个就是最少步数。如何判断重复是一个问题,有很多人用哈希表哈希函数,本人学艺不精不会使用哈希(捂脸),康拓展开是数学上的一个公式,这个公式运用于判断一个数在该数全排列下第几个。

定义:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

eg:数213在123的全排列下面是第X+1个数

        2的后面有1个数比2小,即 1 * 2!

        1的后面没有比1小的数,即 0 * 1!

        3的后面没有比3小的数,即 0 * 0!

        X = 1*2!+0*1!+0*0! = 2

        123的全排列: 123  132  213 231 312 321

九宫最多有9!种排列组合,既362880中排列组合方式,使用数组state[362880]可以用来判断是否出现重复的元素。

使用bfs搜索需要使用队列这一数据结构,曾尝试过使用STL中的queue但是失败了(捂脸),下面代码使用得是队列先进先出的特性。

#include
#include
#include
using namespace std;

int state[362880];  //判断是否重复
int step[362880];  //存储步数
int bnum,bkt;
int dx[] = {-1,1,0,0};  //上下左右
int dy[] = {0,0,-1,1};
typedef int type[9];
type q[362880];
type a,b;  //a为初始状态,b为最终状态
type tem,tem2;

int kangtuo(int x[])  //康拓展开判断是否重复
{
	int fac[]={1,1,2,6,24,120,720,5040,40320};
	int i,j,t,sum;
	sum = 0;
	for(i=0;i<9;i++)
	{
		t = 0;
		for(j=i+1;j<9;j++)
		{
			if(x[j]=0 && yy>=0 && xx<3 && yy<3)  //如果移动没有越界
			{
				p = xx*3+yy;
				memcpy(tem2,tem,sizeof(tem));  //将tem拷贝到tem2上面
				tem2[i] = tem2[p];  //交换p和i的值,既移动0的位置
				tem2[p] = 0;
				if(kangtuo(tem2))
				{
					memcpy(q[rear],tem2,sizeof(tem2));
					step[rear] = step[front]+1;
					rear++;
				}
			}
		}
		front++;
	}
	return -1;
}

int main()
{
	memset(state,0,sizeof(state));
	int i,anum;
	string str1,str2;
	cin>>str1;
	cin>>str2;
	for(i=0;i<9;i++)  //将'.'转换成0
	{
		if(str1[i]>'0'&&str1[i]<='9')
			a[i] = str1[i]-'0';
		else
		{
			a[i] = 0;
			anum = i;
		}
	}
	for(i=0;i<9;i++)
	{
		if(str2[i]>'0'&&str2[i]<='9')
			b[i] = str2[i]-'0';
		else
		{
			b[i] = 0;
			bnum = i;
		}
	}
	int road = bfs();  //根据输出最后结果
	if(road == -1)
		cout<

最后提一句,重排九宫就是经典bfs算法中的八数码,这里有收藏的八数码的八种境界,适合新手看一下

http://blog.csdn.net/kopyh/article/details/48442415#t7

你可能感兴趣的:(C/C++,算法设计与分析,蓝桥杯,分支限界法,bfs,广度优先搜索)