UVA10085

题目的意思就是,可以把0的上下左右和0交换 , 从给出的状态,到达所有每一种状态。每一种状态都有一个最小到达步骤数,问哪个状态的最小到达步骤最大。输出这是的状态(这时的九宫格)还有到达这种状态做了哪些移动,


这题就是用bfs()来搜索,但没有任何结束条件,就是要一直搜到所有状态都找过去,每次搜都要记录用了多少步骤,和移动步骤的字符串。

最后输出bfs最后一层的 一个状态,和到达步骤。搜索过程中要去重,我用的是把九个数字变成一个九位数,判断是否访问过,用map映射;


AC代码:


#include<iostream>
#include<stdio.h>
#include<map>
#include<queue>
#include<string>
using namespace std;
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
char dir[] = {"DURL"};
struct state {
	int s[3][3];
	int x,y;
	string str;
	int pac;
}st1,st2;
string ans;
int fina[3][3];
int res[3][3];
int mi;
int x;
int y;
queue<state> q;
map<long long ,int> m;
bool repeated (state st) {
	int flag = 0;
	long long fin = 0;
	for (int i = 0 ;i < 3 ;i++) {
		for (int j = 0 ;j < 3 ;j++) {
			fin = fin * 10 + st.s[i][j];
		}
	}
	if (m[fin] != 0) 
		return true;
	return false;

}
void setmap (state st) {
	int flag = 0;
	long long fin = 0;
	for (int i = 0 ;i < 3 ;i++) {
		for (int j = 0 ;j < 3 ;j++) {
			fin = fin * 10 + st.s[i][j];
		}
	}
	m[fin] = 1;
}
void bfs() {
	for (int i = 0 ; i < 3 ;i++) {
		for (int j = 0 ; j < 3 ;j++) {
			st1.s[i][j] = res[i][j];
		}
	}
	st1.str = "";
	st1.pac = 0;
	st1.x = x;
	st1.y = y;
	mi = 0;
	setmap(st1);
	q.push(st1);
	while (!q.empty()) {
		st1 = q.front();
		q.pop();
		for (int i = 0 ; i < 4 ;i++) {
			st2 = st1;
			int xx = st2.x;
			int yy = st2.y;
			int nx = xx + dx[i];
			int ny = yy + dy[i];
	//		cout << xx <<" "<< yy<<endl;;
	//		cout << nx <<" "<< ny <<endl;
			if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3) {
				st2.s[xx][yy] = st2.s[nx][ny];
				st2.s[nx][ny] = 0;
				if(repeated(st2))  {	
					continue;
				}
				st2.pac += 1;
				st2.str += dir[i];
				st2.x = nx;
				st2.y = ny;
				q.push(st2);
				setmap(st2);
				if (st2.pac > mi) {
					mi = st2.pac;
					ans = st2.str;
					for (int i = 0 ;i < 3;i++) {
						for (int j = 0 ; j < 3 ;j++) {
							fina[i][j] = st2.s[i][j];
						}
					}
				}
			}	
		}
	}
	return ;
}
int main () {
	int t;
	cin >> t;
	int Case = 1;
	while(t--) {
		m.clear();
		while(!q.empty()) 
			q.pop();
		for (int i = 0 ; i < 3;i++) {
			for (int j = 0 ; j < 3 ;j++) {
				scanf("%d",&res[i][j]);
				if (res[i][j] == 0) {
					x = i;
					y = j;
				}
			}
		}
	//	for (int i = 0 ; i < 3;i++) {
	//		for (int j = 0 ; j< 3; j++) {
	//			if (j != 0)
	//				cout << " ";
	//			cout << res[i][j];
	//		}
	//		cout << endl;
	//	}
	//	cout << endl;
		bfs() ;
		cout << "Puzzle #" << Case++ <<endl;
		for (int i = 0 ;i < 3 ;i++) {
			for (int j = 0 ; j < 3 ;j++) {
				if (j != 0)
					printf(" ");
				printf("%d",fina[i][j]);
			}
			printf("\n");
		}
		cout << ans << endl<<endl;
	}
	return 0 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值