有一个 m×n 格的迷宫(表示有 m 行、n 列),其中有可走的也有不可走的,如果用 1表示可以走,0表示不可以走,文件读入这 m×n 个数据和起始点、结束点(起始点和结束点都是用两个数据来描述的,分别表示这个点的行号和列号)。现在要你编程找出所有可行的道路,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出相应信息(用 −1 表示无路)。
优先顺序:左上右下。数据保证随机生成。
输入格式
第一行是两个数 m,n(1
输出格式
所有可行的路径,描述一个点时用 (x,y) 的形式,除开始点外,其他的都要用 ->
表示方向。
如果没有一条可行的路则输出 −1。
输入输出样例
输入 #1
5 6
1 0 0 1 0 1
1 1 1 1 1 1
0 0 1 1 1 0
1 1 1 1 1 0
1 1 1 0 1 1
1 1
5 6
输出 #1
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
说明/提示
数据保证随机生成。事实上,如果 n=m=14 且每个位置都是 1 的话,有 69450664761521361664274701548907358996488 种路径。
题目有点多!
题目坑点:
1.如果没有解要输出-1。
2.搜索前进的方向要遵循左上右下的优先顺序。
3.首先需要仔细模拟确定行走方向,左下右上(同2)
其实深搜可以写成两种形式,递归和递推形式,但实际上本人跟喜欢递推形式的。
一般情况
首先看题,在不考虑输出路径的情况下这就是一个普通的搜索。
对于一般情况来说我们只需要对当前位置向四周搜索就行了。
这时我们需要考虑3点: 1.对于达到终点的情况; 2.对于该点是否能走的情况
对于1.这是我们递龟递归的终点,在到达这里时便可以结束搜索
而对于2.我们要判断该点是否可走。对于迷宫中的0和已走过的点(避免单一路径中重复输出)不能走,因此使用一个二维数组来存放。
对于路径储存
我们通过看题目还可以知道:
本题目除了常规的深搜外还要记录搜索路径。因此我们使用Vector来存储(相当于一个可以伸缩的数组)。
我们将每一个搜索的点都放入数组中,退出时删除。 在搜到重点时输出 。
这题感觉就基本上裸dfs修改一下限制条件之后再写个输出函数和路径数组就好了。
主要就这些:
1.肯定是搜索(dfs/bfs)
2.有四个方向
3.定义dx[]和dy
4.先定义各种奇奇怪怪的东西
5.然后再打一下打印过程
6.开始搜索
7.注意方向及顺序
8.坐标分为横坐标和纵坐标
9.所以用struct好一些(或者用pair
10.搜索时按照四个方向
11.对于每个方向,要递归一下
12.不要忘了回溯
13.注意搜索时坐标有条件,map数组也有条件(详见代码)
14.主函数别忘了初始化
15.提交,WA,前两个点错了
16.为什么为什么(要判断,定义一个flag)
17.最后输出-1
18.提交,AC
最后附上链接——题目在这里!!!没有账号的要先注册(应该不用说了)
如何注册洛谷账号,请看下面:
1.打开洛谷首页
这样就对了!!!
2.点击注册
当显示以上页面时表示进入了注册页面。
3.登录
当注册好后就可以登陆了。
当显示以上页面时表示进入了登录页面。
#include
#include
using namespace std;
const int N = 5000;
const int dx[4] = {0, -1, 0, 1}, dy[4] = {-1, 0, 1, 0};
int g[N][N], d[N][5];
bool map[N][N];
int n, m, sx, sy, ex, ey, f, ans;
void dfs(int x1, int y1)
{
if(x1 == ex && y1 == ey)
{
ans ++;
cout << '(' << sx << ',' << sy << ')' << "->";
for(int i = 0; i < f; i ++ )
{
if(i != f - 1) cout << '(' << d[i][0] << ',' << d[i][1] << ')' << "->";
else cout << '(' << d[i][0] << ',' << d[i][1] << ')' << endl;
}
return ;
}
for(int i = 0; i < 4; i ++ )
{
int x = x1 + dx[i], y = y1 + dy[i];
if(x >= 1 && x <= n && y >= 1 && y <= m && !map[x][y] && g[x][y] == 1)
{
map[x][y] = true;
d[f][0] = x, d[f][1] = y;
f ++;
dfs(x, y);
map[x][y] = false;
f --;
}
}
}
signed main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ )
{
for(int j = 1; j <= m; j ++ ) scanf("%d", &g[i][j]);
}
scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
map[sx][sy] = true; //标记起点
dfs(sx, sy);
if(ans == 0) cout << -1 << endl;
}