八数码问题

时隔半月,我终于回来了!!!
今天就弱弱地给大佬们讲一下八数码问题吧。
网上的题目和扩展都挺多,那么我先给大家带来这题(戳这里

题目意思我不再赘述了吧。。
这种题一看就知道是搜索吧,但是扩展方式比较复杂,所以我采用了BFS。
首先,我把读入的两个矩阵转换成字符串(比较好处理)。
然后,根据规则,我们可以从四个方向来进行扩展。

扩展时,我们先找到0的位置,并设置边界条件。
我就以0与上一行交换为例子,易得,0不可能是在3*3矩阵的第一行的,即0的位置pos!=0,1,2。剩下的三个扩展方式的边界条件请读者自行思考。

但这时,另一个棘手的问题出现了,既然已经转换成字符串,我们统计答案的难度就加大了。这时我们就要用到一个STL容器——map。我们将字符串映射到一个整数上,这样,我们就可以统计答案了,即已扩展的字符串所用的操作数为原有字符串用的操作数加一,至此,这道题的难点已经全部处理完了,剩下的还有一些小细节需要读者注意。

代码如下

#include<bits/stdc++.h>
using namespace std;
int pps[]= {0,1,2,6,7,8,0,3,6,2,5,8};
int turn[]= {-3,3,-1,1};//因为懒得将BFS敲四遍,我就直接将需要移动的步数存在一个数组里了,看的也比较简洁明了
map<string,int>mp;
queue<string>q;
int G1[4][4],G2[4][4];
string head,tail;
int step=0,Cnt=0;                                                                                                                            
struct BFS {
	void Calc(string x,int dep) {
		int kk=x.length(),now;
		string p=x;
		for(int i=0;i<kk;i++)if(x[i]=='0')now=i;
		if(now==pps[dep*3]||now==pps[dep*3+1]||now==pps[dep*3+2])return ;
		x[now]=p[now+turn[dep]],x[now+turn[dep]]=p[now];
		if(mp.count(x)==0){
			q.push(x);
			mp[x]=mp[p]+1;
		}
		return ;
	}
	void Solve(){
		q.push(head);
		mp[head]=0;
		while(!q.empty()){
			if(mp[q.front()]>20){puts("No solution!");return ;}
			Calc(q.front(),0);
			Calc(q.front(),1);
			Calc(q.front(),2);
			Calc(q.front(),3);
			q.pop();
			if(mp.count(tail)!=0){printf("%d\n",mp[tail]);return ;}
		}		
	}
}k;
int main() {
	//freopen("8.in","r",stdin);
	//freopen("8.out","w",stdout);
	for(int i=1; i<=3; i++)for(int j=1; j<=3; j++)scanf("%d",&G1[i][j]);
	for(int i=1; i<=3; i++)for(int j=1; j<=3; j++)scanf("%d",&G2[i][j]);
	char tot1,tot2;
	for(int i=1; i<=3; i++)for(int j=1; j<=3; j++)tot1=(char)(G1[i][j]+'0'),head+=tot1;
	for(int i=1; i<=3; i++)for(int j=1; j<=3; j++)tot2=(char)(G2[i][j]+'0'),tail+=tot2;
	k.Solve();
	return 0;

推荐题目
1、洛谷1379
2、洛谷2578尽管我现在还没做

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值