洛谷P1379_八数码游戏

#include<iostream>
#include<queue>
#include<map>
#include <cstdio>

using namespace std;

queue <int> q1;//记录状态

map <int, int> step;//记录步数

int dr[4] = {0, 1, 0, -1};
int dc[4] = {-1, 0, 1, 0};

int bfs();
bool canmoveto(int u, int dir);
int moveto(int u, int dir);

int main()
{

	int n, ans;
	scanf("%d", &n);
	if(n == 123804765)
    {//特殊情况
        printf("0\n");
        return 0;
    }
    q1.push(n);
	step[n] = 0;
	ans = bfs();
	printf("%d\n", ans);
	return (0);
}

int bfs()
{
	int i, u, v;
	while(!q1.empty())
	{
		u = q1.front();
		q1.pop();
		for(i = 0; i < 4; i++)
		{
			if(canmoveto(u, i))
			{//如果能扩展
				v = moveto(u, i);//v是u扩展的元素
				if(v == 123804765)//如果v满足条件,就返回到达它的步数
					return(step[u] + 1);
				if(!step.count(v))//如果v是未被扩展的,就入队
				{
					q1.push(v);
					step[v] = step[u] + 1;
				}
			}
		}
	}
	return -1;
}

bool canmoveto(int u, int dir)
{
	int i, j;
	int b[3][3];
	int row, col;       //队首0的位置
	int r, c;           //由队首拓展的0的位置
	for(i = 2; i >= 0; i--)
	{
		for(j = 2; j >= 0; j--)
		{
			b[i][j] = u % 10;
			u /= 10;
			if(!b[i][j]) row = i, col = j;
		}
	}
	r = row + dr[dir];
	c = col + dc[dir];
    if(r >= 0 && r < 3 && c >= 0 && c < 3)
		return 1;
	return 0;
}

int moveto(int u, int dir)
{
	int i, j;
	int b[3][3];
	int row, col;
	int r, c;
	int v;
	for(i = 2; i >= 0; i--)
	{
		for(j = 2; j >= 0; j--)
		{
			b[i][j] = u % 10;
			u /= 10;
			if(!b[i][j]) row = i, col = j;
		}
	}
	r = row + dr[dir];
	c = col + dc[dir];
	b[row][col] = b[r][c];
	b[r][c] = 0;
	v = 0;
	for(i = 0; i < 3; i++)
		for(j = 0; j < 3; j++)
			v = v * 10 + b[i][j];
	return v;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/80247002