算法笔记8.2 BFS的应用,8数码问题

地址: http://codeup.cn/problem.php?cid=100000609&pid=2

思路:用BFS算法来完成。可以看成是走迷宫的改版

从第一矩阵变成第二矩阵,实际上可以看成 是0的位置移动
2 8 3	1 2 3
1 6 4	8 0 4
7 0 5 	7 6 5

# # #	# # #	# 0 #	0 # #	# # #	# # #
# # #	# 0 #	# # #	# # #	0 # #	# 0 #	
# 0 #	# # #	# # #	# # #	# # #	# # #

从当前位置出发,把每一层的可能性都枚举出来,放入队列中,直到达到矩阵相等。
注意
1.期间0可能绕一个圈,又回到原位置。但是与此同时也有0正在朝正确的
道路前进,因此不是死循环。除非题目有问题。。。
2.Node.step = top.step +1 ; //注意是将上一层的步数相加,不是自增

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;

int matrix[3][3],final[3][3];

int X[4] = {0,1,0,-1};		//数组增量,代表上下左右 
int Y[4] = {1,0,-1,0};

struct node{
	
	int x,y;		//0的位置 
	int M[3][3];	//此时的矩阵 
	int last_x,last_y;	//上一个状态时,0的位置 
	int step;		//移动的步数 
}Node; 

bool judge(int x, int y){
	if(x<0|| y<0|| x>=3|| y>=3) return false;
	else 
		return true; 
}

	//判定是否与最终结果矩阵相同 
bool same(int a[3][3]){
	for(int i=0; i<3; i++){
		for(int j=0; j<3; j++)
			if( a[i][j] != final[i][j] )
				return false; 
	}
	return true;
}

int BFS(int x, int y){
	
	queue<node> Q;
	Node.x = x,Node.y = y;	//将第一步的0的位置,步数储存 
	Node.step = 1;
	for(int i=0; i<3;i++)
		for(int j=0; j<3; j++)
			Node.M[i][j] = matrix[i][j]; 	//第一步时,存好矩阵 
			
	Q.push(Node);
	
	while(!Q.empty()){
		
		node top = Q.front();
		Q.pop();
		
		for(int i=0;i<4;i++){
			
			int newX = top.x + X[i];
			int newY = top.y + Y[i];
				//若不越界且移动后的位置不是原来的位置 
			if( judge(newX,newY) && (top.last_x !=newX || top.last_y !=newY ) ){
				//则将 0 移动到新的位置 
				Node.x = newX;
				Node.y = newY;
				Node.last_x = top.x;
				Node.last_y = top.y;
				Node.step  = top.step +1 ;		//注意是将上一层的步数相加,不是自增 
				for(int i=0; i<3;i++)
					for(int j=0; j<3; j++)
						Node.M[i][j] = top.M[i][j]; 
				
				swap(Node.M[newX][newY] , Node.M[top.x][top.y] );
				if(same(Node.M)) return Node.step;
				Q.push(Node);	
			}
		}
	}
	
	return -1;		//事实上不会发生错误... 
}

int main(){
	
	int x_0,y_0;
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			scanf("%d" , &matrix[i][j]);
			if(matrix[i][j] == 0){
				x_0 = i;
				y_0 = j;
			} 
		}
	}
	
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			scanf("%d" , &final[i][j]);
		}
	}	
			
	printf("%d" , BFS(x_0,y_0))	;	
	return 0;
	
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值