(9)八数码

八数码问题:编号为188个正方形滑块被摆成33列(有一个格子留空),如图7-

14所示。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就成为了新的空格。给定初始局面和目标局面(用0表示空格),你的任务是计算出最少的移动步数。如果无法到达目标局面,则输出-1


路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条从初始状态到终止状态的最优路径,而不是像回溯法那样找到一个符合某些要求的解。

#include<iostream>
#include<iomanip>
#include<set>
#include<queue>
#include<map>
using namespace std;
//使用直接哈希的状态数组来判重
//广度用队列
//深度用递归 
set<int> vis;
queue<int> que;
//打印路径需要一个状态空间大小的数组记录父亲 
int end = 815736402;

bool dowork(int number){
	if(number == end) return true;
	if(0 == vis.count(number)){
		que.push(number);
		vis.insert(number);
	}
	return false;
}

bool bfs(int number){
	int init = number;
	cout <<number<<"\n";
	int s[5][5] = {};
	s[1][1] = number/100000000;
	s[1][2] = number/10000000%10;
	s[1][3] = number/1000000%10;
	s[2][1] = number/100000%10;
	s[2][2] = number/10000%10;
	s[2][3] = number/1000%10;
	s[3][1] = number/100%10;
	s[3][2] = number/10%10;
	s[3][3] = number/1%10;
	for(int i=1;i<=3;i++){
		for(int j=1;j<=3;j++){
			if(s[i][j] == 0 ){
				
				s[i][j] = s[i-1][j];
				s[i-1][j] = 0;
				number = s[1][1]*100000000	+s[1][2]*10000000	+s[1][3]*1000000
					+s[2][1]*100000	+s[2][2]*10000	+s[2][3]*1000
					+s[3][1]*100	+s[3][2]*10	+s[3][3]*1;
				if(dowork(number)) return true;
				s[i-1][j] = s[i][j];
				s[i][j] = 0;
				
				s[i][j] = s[i+1][j];
				s[i+1][j] = 0;
				number = s[1][1]*100000000	+s[1][2]*10000000	+s[1][3]*1000000
					+s[2][1]*100000	+s[2][2]*10000	+s[2][3]*1000
					+s[3][1]*100	+s[3][2]*10	+s[3][3]*1;
				if(dowork(number)) return true;
				s[i+1][j] = s[i][j];
				s[i][j] = 0;
				
				s[i][j] = s[i][j-1];
				s[i][j-1] = 0;
				number = s[1][1]*100000000	+s[1][2]*10000000	+s[1][3]*1000000
					+s[2][1]*100000	+s[2][2]*10000	+s[2][3]*1000
					+s[3][1]*100	+s[3][2]*10	+s[3][3]*1;
				if(dowork(number)) return true;
				s[i][j-1] = s[i][j];
				s[i][j] = 0;
				
				s[i][j] = s[i][j+1];
				s[i][j+1] = 0;
				number = s[1][1]*100000000	+s[1][2]*10000000	+s[1][3]*1000000
					+s[2][1]*100000	+s[2][2]*10000	+s[2][3]*1000
					+s[3][1]*100	+s[3][2]*10	+s[3][3]*1;
				if(dowork(number)) return true;
				s[i][j+1] = s[i][j];
				s[i][j] = 0;
				return false;
			}
		}
	}
}

int main(){
	vis.clear();
	freopen("eightNumberQuestion.in","r",stdin);
	freopen("eightNumberQuestion.out","w",stdout);
	int s[5][5] = {};
	cin >>s[1][1]>> s[1][2]>> s[1][3];
	cin >>s[2][1]>> s[2][2]>> s[2][3];
	cin >>s[3][1]>> s[3][2]>> s[3][3];
	int number = s[1][1]*100000000	+s[1][2]*10000000	+s[1][3]*1000000
					+s[2][1]*100000	+s[2][2]*10000	+s[2][3]*1000
					+s[3][1]*100	+s[3][2]*10	+s[3][3]*1;
	que.push(number);
	while(!que.empty()){
		number = que.front();
		que.pop();
		if(bfs(number)) break;
	}
	cout << "true";
	fclose(stdin);
	fclose(stdout);
}

输出文件略大。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值