题目描述
给定一个 N × M N \times M N×M 方格的迷宫,迷宫里有 T T T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N , M , T N,M,T N,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 S X , S Y , F X , F Y SX,SY,FX,FY SX,SY,FX,FY, S X , S Y SX,SY SX,SY 代表起点坐标, F X , F Y FX,FY FX,FY 代表终点坐标。
接下来 T T T 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
样例 #1
样例输入 #1
2 2 1
1 1 2 2
1 2
样例输出 #1
1
提示
对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 5 1 \le N,M \le 5 1≤N,M≤5, 1 ≤ T ≤ 10 1 \le T \le 10 1≤T≤10, 1 ≤ S X , F X ≤ n 1 \le SX,FX \le n 1≤SX,FX≤n, 1 ≤ S Y , F Y ≤ m 1 \le SY,FY \le m 1≤SY,FY≤m。
解题思路:
题目要求就是找出所有从起点到终点的路径,那么就可以采用深度优先搜索来找出每一条路径
我们逐步来实现递归函数
首先,参数列表部分,只需传入x、y用以代表当前坐标
void deep_first_search(int x, int y);
然后,我们来实现递归主体部分
先进行准备工作
创建一个二维数组,来表示地图
再创建一个二维数组,用来标记走过的格子
再再创建一个二维数组,用来存储四个方向
bool map[5][5] = { 0 };//读入地图,0为平地,1为障碍物
bool map_book[5][5] = { 0 };//标记走过的路,0为未走过,1为走过,防止重复
int step[4][2] = //按右、下、左、上四个方向尝试
{
{0, 1},
{1, 0},
{0, -1},
{-1, 0}
};
准备工作完成,开始实现
for循环尝试四个方向,判断是否可行
若可行,则标记该格子已经走过,然后进入这一个格子,重复以上步骤
此外,在递归返回后不要忘记取消标记
void deep_first_search(int x, int y)//利用深度优先搜索寻找每一条路径,x、y分别代表当前坐标
{
//递归主体
for (int i = 0; i < 4; i++)//尝试每一个方向
{
int temp_x = x + step[i][0];
int temp_y = y + step[i][1];
if (map_book[temp_x][temp_y] || map[temp_x][temp_y])//如果走过或者遇到障碍物,尝试下一个方向
{
continue;
}
else if (temp_x < 0 || temp_x > N - 1 || temp_y < 0 || temp_y > M - 1)//如果出界,尝试下一个方向
{
continue;
}
map_book[temp_x][temp_y] = true;//标记为已经走过
deep_first_search(temp_x, temp_y);
map_book[temp_x][temp_y] = false;//取消标记
}
return;
}
最后,递归停止条件当然就是当前坐标与终点坐标相等了
void deep_first_search(int x, int y)//利用深度优先搜索寻找每一条路径,x、y分别代表当前坐标
{
//递归结束条件
if (x == final_x - 1 && y == final_y - 1)
{
sum_path++;//找到一条符合条件的路径
return;
}
//递归主体
for (int i = 0; i < 4; i++)//尝试每一个方向
{
int temp_x = x + step[i][0];
int temp_y = y + step[i][1];
if (map_book[temp_x][temp_y] || map[temp_x][temp_y])//如果走过或者遇到障碍物,尝试下一个方向
{
continue;
}
else if (temp_x < 0 || temp_x > N - 1 || temp_y < 0 || temp_y > M - 1)//如果出界,尝试下一个方向
{
continue;
}
map_book[temp_x][temp_y] = true;//标记为已经走过
deep_first_search(temp_x, temp_y);
map_book[temp_x][temp_y] = false;//取消标记
}
return;
}
至此,本题核心解题部分说明完毕
完整代码如下
#include <iostream>
using namespace std;
int sum_path = 0;//用于累计总数
int N, M;//分别代表长度和宽度
int final_x, final_y;//代表终点坐标
bool map[5][5] = { 0 };//读入地图,0为平地,1为障碍物
bool map_book[5][5] = { 0 };//标记走过的路,0为未走过,1为走过,防止重复
int step[4][2] = //按右、下、左、上四个方向尝试
{
{0, 1},
{1, 0},
{0, -1},
{-1, 0}
};
//void out_put_path()//输出路径
//{
// for (int i = 0; i < N; i++)
// {
// for (int j = 0; j < M; j++)
// {
// putchar(char(map_book[i][j] + '0'));
// putchar(' ');
// }
// putchar('\n');
// }
//}
void deep_first_search(int x, int y)//利用深度优先搜索寻找每一条路径,x、y分别代表当前坐标
{
//递归结束条件
if (x == final_x - 1 && y == final_y - 1)
{
sum_path++;//找到一条符合条件的路径
//out_put_path();//显示路径
//putchar('\n');
return;
}
//递归主体
for (int i = 0; i < 4; i++)//尝试每一个方向
{
int temp_x = x + step[i][0];
int temp_y = y + step[i][1];
if (map_book[temp_x][temp_y] || map[temp_x][temp_y])//如果走过或者遇到障碍物,尝试下一个方向
{
continue;
}
else if (temp_x < 0 || temp_x > N - 1 || temp_y < 0 || temp_y > M - 1)//如果出界,尝试下一个方向
{
continue;
}
map_book[temp_x][temp_y] = true;//标记为已经走过
deep_first_search(temp_x, temp_y);
map_book[temp_x][temp_y] = false;//取消标记
}
return;
}
int main()
{
int T, start_x, start_y, obstacle_x, obstacle_y;
cin >> N >> M >> T;
cin >> start_x >> start_y;
cin >> final_x >> final_y;
for (int i = 0; i < T; i++)
{
cin >> obstacle_x >> obstacle_y;
map[obstacle_x - 1][obstacle_y - 1] = true;//添加障碍物
}
map_book[start_x - 1][start_y - 1] = true;//注意要将起点标记
deep_first_search(start_x - 1, start_y - 1);
cout << sum_path;
return 0;
}