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

历届试题 九宫重排  
时间限制:1.0s   内存限制:256.0MB
       
问题描述
  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
蓝桥杯 历届试题 九宫重排 (广搜)_第1张图片 蓝桥杯 历届试题 九宫重排 (广搜)_第2张图片
  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
  输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22

主要是标记剪枝,我用的set,不过听学长说可以用康托展开,可是康托展开好难。。

写得挺蠢的也过了,蓝桥数据应该挺水的吧。。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
char map1[5][5], map2[5][5];
int b1x, b1y;
struct node {
	int x, y, step;
	char m[5][5];
};
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
set<string> s;
int bfs() {
	queue<node> q;
	node now, next;
	now.x = b1x, now.y = b1y, now.step = 0;
	memcpy(now.m, map1, sizeof(map1));
	char tstr[10];
	int i, j, k = 0;
	for(i = 1; i <= 3; i++) {
		for(j = 1; j <= 3; j++) {
			tstr[k++] = map1[i][j];
		}
	}
	tstr[k] = 0;
	string str(tstr);  //字符数组转string 
	s.insert(str);
	q.push(now);
	while(!q.empty()) {
		now = q.front();
		q.pop();
		int flag = 0;
		for(i = 1; i <= 3; i++) {  //退出条件 
			for(j = 1; j <= 3; j++) {
				if(now.m[i][j] != map2[i][j]) {
					flag = 1;
					break;
				}
			}
			if(flag) break;
		}
		if(i == 4) return now.step;
		for(i = 0; i < 4; i++) {
			next.x = now.x + dir[i][0];
			next.y = now.y + dir[i][1];
			next.step = now.step + 1;
			if(next.x < 1 || next.x > 3 || next.y < 1 || next.y > 3) continue;
			memcpy(next.m, now.m, sizeof(now.m));
			next.m[now.x][now.y] = next.m[next.x][next.y];
			next.m[next.x][next.y] = '.';
			int i, j, k = 0;
			for(i = 1; i <= 3; i++) {
				for(j = 1; j <= 3; j++) {
					tstr[k++] = next.m[i][j];
				}
			}
			string str1(tstr);
			if(s.count(str1) == 1) continue;
			else s.insert(str1);
			q.push(next);
		}
	}
	return -1; 
}
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int i, j;
	for(i = 1; i <= 3; i++) {
		for(j = 1; j <= 3; j++) {
			scanf("%c", &map1[i][j]);
			if(map1[i][j] == '.') b1x = i, b1y = j; 
		}
	}
	getchar();
	for(i = 1; i <= 3; i++) {
		for(j = 1; j <= 3; j++) {
			scanf("%c", &map2[i][j]);
		}
	}
	getchar();
	cout << bfs() << endl;
	return 0;
}


你可能感兴趣的:(蓝桥杯 历届试题 九宫重排 (广搜))