【机试练习】【C++】【codeup 5997】【宽搜入门】8数码难题

24 篇文章 0 订阅

参考:https://blog.csdn.net/weirdo_coder/article/details/89167900
并给出了自己的一些更改,提高了可读性,降低了算法效率。

#include<cstdio>
#include<map> 
#include<algorithm>
#include<queue>
using namespace std;

struct Node{
	int M[3][3]; // 棋盘本身 
	int x0 = -1, y0 = -1; // 存储0的位置 
	int step = -1;
};

int to_mirror(int m[3][3]){
	int target_mirror = 0;
	for(int i = 0; i < 3 ; i ++){
		for(int j = 0; j < 3; j ++){
			target_mirror *= 10;
			target_mirror += m[i][j];
		}
	}
	return target_mirror;
}

// 这个函数没有用到 可以不看
void to_m(int mirror, Node *n){
	for(int i = 2; i >= 0; i --){
		for(int j = 2; j >= 0; j --){
			int target = mirror % 10;
			n -> M[i][j] = target;
			mirror /= 10;
		}
	}
}

map<int, bool> bfs_map;
Node start_m, end_m;
queue<Node> Q;
// 这是增量数组 
// 按照胡凡《算法笔记》上的套路,就应该按真实的上下左右设置增量数组
// 这样比较简单,易懂
int X[4] = {0, -1, 0, 1};
int Y[4] = {-1, 0, 1, 0};

// 判断一个点是否合法 
bool judge(int x, int y){
	if(x > 2 || y > 2 || x < 0 || y < 0){
		return false;
	}
	return true;
}
// 实际交换0和其他值的函数
void change(Node* n, int change_x, int change_y){
	swap(n -> M[n -> x0][n -> y0], n -> M[n -> x0 + change_x][n -> y0 + change_y]);
	n -> x0 += change_x;
	n -> y0 += change_y;
}

int main(){
	// 读入 
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 3; j++){
			scanf("%d", &(start_m.M[i][j]));
			if(start_m.M[i][j] == 0){
				start_m.x0 = i;
				start_m.y0 = j;
			}
		}
	}
	start_m.step = 1; // 题目要求走start的步数为1 
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 3; j++){
			scanf("%d", &(end_m.M[i][j]));
			if(end_m.M[i][j] == 0){
				end_m.x0 = i;
				end_m.y0 = j;
			}
		}
	}
	
	int end_mirror = to_mirror(end_m.M);
	if(to_mirror(start_m.M) == end_mirror){
		printf("1");
		return 0;	
	}
	Q.push(start_m);
	bfs_map[to_mirror(start_m.M)] = true;
	while(!Q.empty()){
		Node tnode = Q.front();
		Q.pop();
		for(int i = 0; i < 4; i ++){
			Node tmp = tnode;
			// 取增量
			int change_x = X[i];
			int change_y = Y[i];
			// 判断当前能不能换
			if(judge(tmp.x0 + change_x, tmp.y0 + change_y)){
				// 换 
				change(&tmp, change_x, change_y);
				// 判断当前状态有没有换过
				int tmp_mirror = to_mirror(tmp.M);
				if(!bfs_map[tmp_mirror]){
					bfs_map[tmp_mirror] = true;
					tmp.step ++;
					if(tmp_mirror == end_mirror){
						 end_m.step = tmp.step;
						 break;
					}
					Q.push(tmp);
				}
			} 	 
		}
	}
	printf("%d", end_m.step);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值