[蓝桥杯]九宫重排

[C++]九宫重排

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

输入:
12345678.
123.46758
输出:
3

解题思路:可以使用bfs,由于时间限制,需要使用双向bfs,对初态和终态进行bfs,当两边状态变化到一种形态时,表示可以达到。即maps值为1,是由初态变化而来,为2的话,是由终态变化而来。当maps值相加为3的时候,则证明初态和终态都能达到此状态。

#include<iostream>
#include<map>
#include<queue>
#include<string>
using namespace std;

int ne[4][2] = {1,0,-1,0,0,1,0,-1};
map<string, int> maps;
map<string, int> temp;
string a, b;

/*
	双向bfs 
*/
int bfs(){
	if(a == b)
		return 0;
	queue<string> que;
	que.push(a);
	que.push(b);
	while(!que.empty()) {
		string head = que.front();
		que.pop();
		
		char t;
		int x, y;
		for(int i = 0; i<3; i++){
			for(int j = 0; j<3; j++){
				t = i*3+j;
				if(head[t] == '.'){
					x = i;
					y = j;
					break;
				}
			}
		}
		t = x*3+y;
		for(int i = 0; i<4; i++){
			int nx = x + ne[i][0];
			int ny = y + ne[i][1];
			if(nx>=0 && nx<3 && ny>=0 && ny < 3){
				string tail = head;
				tail[t] = head[nx*3+ny];
				tail[nx*3+ny] = head[t];
				if(!maps[tail]) {
					maps[tail] = maps[head];   //区分由a转化而来还是由b转化而来 
					temp[tail] = temp[head]+1; //移动步数加1 
					que.push(tail);
				}
				else if(maps[tail] + maps[head] == 3){
					return temp[tail]+temp[head]+1;
				}
			}
		}
	}
	return -1;
}

int main(){
	cin>>a>>b;
	/**
	初始化  由a转化而来的maps值为1  由b转化来的maps值为2 
	*/ 
	maps[a] = 1;
	maps[b] = 2;
	
	cout<<bfs()<<endl;
	
	return 0;
}
发布了63 篇原创文章 · 获赞 8 · 访问量 7192

猜你喜欢

转载自blog.csdn.net/s1547156325/article/details/104526669
今日推荐