#386. 八数码

 

有点实力的这题,主要是怎么和0交换是一个问题,还有cnator值是一个新知识,这里就不多讲,cantor值是用来判断全排列下,这一串数排第几。看我代码awa..... 

//给点支持吧QwQ 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 11;
struct node
{
	int a[5][5];    //九宫格的状态 
	int x, y, step;     //每种状态下(0,0)的坐标,step是到达该状态的步骤 
};
ll fact[maxn] = {1,1,2,6,24,120,720,5040,40320,362880,3628800}; // 存储1-10阶乘
int P[maxn]; // 二维转一维
int ans = 0, vis[1000005];          //vis判断某个状态是否已经走过 
int dx[5][2]={{1,0},{-1,0},{0,1},{0,-1}};  
ll fin;
node start, aim;
queue<node> Q;
ll cantor(node x, int n = 9)//cantor值,不讲了..... 
{
	for(int i=1;i<=3;i++)
	{
		for(int j=1;j<=3;j++) 
		{
			P[(i-1)*3+j]=x.a[i][j];
		}
	}
    ll ans=1;
    for(int i=1;i<=n;i++) {
    	for(int j=i+1;j<=n;j++)
		{
    		if(P[i]>P[j])
			{
				ans+=fact[n-i]; // 统计第i位后面有多少比它小的
			}
    	}
    }
    return ans;
}

// void print(node x)
// {
	// for(int i = 1; i <= 3; i++) {
		// for(int j = 1; j <= 3; j++) {
			// cout << x.a[i][j]<<" ";
		// }
		// cout << endl;
	// }
	// cout<<endl;
// }

void bfs()//BFS
{
	Q.push(start);//把start存进Q中 
	vis[cantor(start)]=1;//把start的cantor值 
	while(!Q.empty()) //不空就运行 
	{
		node f=Q.front();//把Q.front()存下来 
		node nxt;
		Q.pop();//把首位吃了 
		if(cantor(f)==fin) //如果f的cantor值是结束状态的fin的话 
		{
			ans=f.step;//ans赋值 
			break;//跳出 
		}
		for(int i=0;i<=4-1;i++) //位移 
		{
			int nx=f.x+dx[i][0];
			int ny=f.y+dx[i][1];
			if(nx>=1&&nx<=3&&ny>=1&&ny<=3) //如果没有出界 
			{
				nxt=f;//nxt赋值 
				swap(nxt.a[f.x][f.y],nxt.a[nx][ny]);//把a数组中的0和这个位置的数交换 
				nxt.x=nx;//nxt的xy设置 
				nxt.y=ny;
				nxt.step=f.step+1;//又走了一步nxt.step=f.step++; 
				if(!vis[cantor(nxt)]) //如果vis[cantor(nxt)]!=1 
				{
					vis[cantor(nxt)]=1;//设为1 
					Q.push(nxt);//把nxt存入Q 
				}
			}
		}
	}
}

int main()
{
	for(int i=1;i<=3;i++) 
	{
		for(int j=1;j<=3;j++) 
		{
			cin>>start.a[i][j];//输入 
			if(start.a[i][j]==0) //找到那里是可以换的 
			{
				start.x=i;//把start的xy设为0的坐标 
				start.y=j;
			}
		}
	}
	start.step=0;//step设为零 
	for(int i=1;i<=3;i++) //输入结束状态 
	{
		for(int j=1;j<=3;j++) 
		{
			cin>>aim.a[i][j];
		}
	}
	fin=cantor(aim); // 结束状态的cantor值 
	bfs();//运行 
	cout<<ans;//输出最少次数 
	return 0;
}

给点支持吧QwQ,马上出BFS.....awa

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值