走迷宫
给定一个n*m的二维整数数组,用来表示一个迷宫,数组中只包含0或1,其中0表示可以走的路,1表示不可通过的墙壁。
最初,有一个人位于左上角(1, 1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角(n, m)处,至少需要移动多少次。
数据保证(1, 1)处和(n, m)处的数字为0,且一定至少存在一条通路。
输入格式
第一行包含两个整数n和m。
接下来n行,每行包含m个整数(0或1),表示完整的二维数组迷宫。
输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤n,m≤100
输入样例
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例
8
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 110;
int n, m;
int g[N][N];
int d[N][N];
PII q[N * N];//模拟队列
int bfs()
{
memset(d, -1, sizeof d);//表示还没有搜到
int hh = 0, tt = 0;
d[0][0] = 0;//从左上角开始走
q[0] = { 0,0 };//第一个点入队
int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };//上下左右的偏移量
while (hh <= tt)//队列不空
{
auto t = q[hh++];//取出队头
for (int i = 0; i < 4; i++)
{
int x = t.first + dx[i], y = t.second + dy[i];//搜索到的点
if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)//在范围内并且未被搜索到
{
d[x][y] = d[t.first][t.second] + 1;//层数加一
q[++tt] = { x,y };//加入队列
}
}
}
return d[n - 1][m - 1];
}
int main()
{
cin >> n >> m;
for (int i = 0; i <n; i++)
for (int j = 0; j <m; j++)
scanf("%d", &g[i][j]);
printf("%d", bfs());
return 0;
}
八数码
给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。
输入格式
输入占一行,将3×3的初始网格描绘出来。
例如,如果初始网格如下所示:
1 2 3
x 4 6
7 5 8
则输入为:1 2 3 x 4 6 7 5 8
输出格式
输出占一行,包含一个整数,表示最少交换次数。
如果不存在解决方案,则输出”-1”。
输入样例
2 3 4 1 5 x 7 6 8
输出样例
19
代码
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<queue>
#include<stdio.h>
using namespace std;
typedef long long LL;
int bfs(string start)
{
string end = "12345678x";//最终状态
queue<string>q;//状态
unordered_map<string, int>d;//距离
q.push(start);//将初始状态入队
d[start] = 0;
int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };//上下左右的偏移量
while (q.size())
{
auto t = q.front();//取出队头
q.pop();
int distance = d[t];
if (end == t)
return distance;
/*状态转移*/
int k = t.find('x');//返回x的位置
int x = k / 3, y = k % 3;//行 列
for (int i = 0; i < 4; i++)
{
int a = x + dx[i];
int b = y + dy[i];
if (a >= 0 && a < 3 && b >= 0 && b < 3)
{
swap(t[k], t[a * 3 + b]);
if (!d.count(t))//查询操作 未被遍历
{
d[t] = distance + 1;//距离加一
q.push(t);//将新状态加入队列
}
swap(t[k], t[a * 3 + b]);//保持原来状态
}
}
}
return -1;//所有状态全部遍历,并且和end不同
}
int main()
{
string start;
for (int i = 0; i < 9; i++)
{
char c;
cin >> c;
start += c;//将九宫格看成字符串
}
cout << bfs(start);
return 0;
}