深度优先搜索(dfs)算法之三——寻路
3.1 例题一、迷宫
题目描述
给定一个 方格的迷宫,迷宫里有 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每 次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 ,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 , 代表起点坐标, 代表终点坐标。
接下来 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
样例 #1
样例输入 #1
2 2 1
1 1 2 2
1 2
样例输出 #1
1
提示
对于 的数据,,,,。
迷宫#include <bits/stdc++.h>
using namespace std;
bool board[15][15];
int n,m,dx[4]={-1,+1,0,0},
dy[4]={0,0,-1,+1};//定义四个方向的相对偏移,简化代码(行数)
int nx,ny,ex,ey,cnt;
//nx,ny起点坐标;ex,ey终点坐标,cnt路径条数
void dfs(int x,int y)
{
if (x ==ex&&y ==ey)//如果到终点
{
cnt++;//路径加一
return;//结束该线路向下递归
}
for (int k=0;k<4;k++)
{
int l=x+dx[k];int r=y+dy[k];
if (l>=1&&r>=1&&l<=n&&r<=m&&!board[l][r])
{
board[l][r]=1;//标记为已访问
dfs(l,r);
board[l][r]=0;//回溯
}
}
return;
}
int main ()
{
int t,zx,zy;
cin>>n>>m>>t>>nx>>ny>>ex>>ey;
board[nx][ny]=1;
while(t--)
{
cin>>zx>>zy;
board[zx][zy]=2;//设为障碍
}
dfs (nx,ny);//从起点开始寻找
cout<<cnt;
return 0;
}
3.2 例题二、下象棋
题目描述
在象棋盘(9*9)中,有一个马在坐标x行y列,现在想跳到n行m列,问在max步内,马有多少种跳到目标位置的方案(不考虑别马腿)?如果有,请输出所有的可能线路。

输入格式
一行 5 个整数,分别表示 x,y,n,m,max,出题人保证不越界
第二行 一个整数,棋盘上棋子个数num
后面num行,每行两个整数,分别是棋子的行和列
输出格式
第一行输出一个整数,表示方案数
接下来若干行,每行一串坐标,从(x,y)到(n,m)一系列坐标,格式如:(3,3) (3,5) (4,6),具体看样例。
最后一行一个整数,方案总数
输入/输出例子1
输入:
5 3 3 6 3
2
1 5
2 8
输出:
(5 3) (3 4) (5 5) (3 6)
(5 3) (3 2) (4 4) (3 6)
(5 3) (3 2) (2 4) (3 6)
(5 3) (6 5) (4 4) (3 6)
(5 3) (6 5) (5 7) (3 6)
(5 3) (7 4) (5 5) (3 6)
(5 3) (4 5) (2 4) (3 6)
(5 3) (4 5) (5 7) (3 6)
8
#include <bits/stdc++.h>
using namespace std;
char board[15][15]; //定义一个
int dx[] = {-2, -2, -1, 1, 1, 2, -1, 2},
dy[] = { 1, -1, -2, 2, -2, 1, 2, -1}; //定义 8 个方向的相对偏移,简化代码(行数)
//cnt路径条数
int x,y,m,n,step,cnt,maxStep;
struct Txy {
int r,c;
} ans[20];
void out( int step) {
for (int i=0; i<=step; i++){
cout <<"("<<ans[i].r<<" ";
cout << ans[i].c<<") ";
}
cout << endl;
}
//x,y起点坐标;
void dfs(int x,int y,int step ) {
ans[step].r=x;
ans[step].c=y;
if(step>maxStep) return;
if(x==n && y==m) {
cnt++;//找到一种方案,路径加一
out(step);
return;//结束该路线向下搜索
}
for (int k=0;k<8;k++) {
//r,c下一个预移动的目标地点的坐标
int r=x+dx[k];int c=y+dy[k];
if (r>=1 && c>=1 && r<=9 && c<=9 && !board[r][c])
{
board[r][c]=1;//标记为已访问
dfs(r,c,step+1);
board[r][c]=0;//回溯
}
}
}
int main () {
cin>>x>>y>>n>>m>>maxStep;
int t;
cin>>t;
while(t--){
int r,c;
cin>>r>>c;
board[r][c]=2;
}
dfs (x,y,0);//从起点开始寻找
cout<<cnt;
return 0;
}
3.3 例题三、将军抽车
根据《[语言月赛 202308] 小粉兔喜欢下象棋吗》 修改
题目描述
在中国象棋中,马走日字形。用 表示第 行第 列的格点,不考虑别马腿,考虑跳出棋盘外,在 的马可以跳到 ,,,,,,, 八个位置。
将军抽车是中国象棋中常用的进攻策略。如下图所示,此时红帅在 ,红车在 。若黑马跳到红框位置所指的 ,帅将由于被将军被迫移动,此时,马就可以吃掉红车。

本题将解决将军抽车的简化版问题。在本题中,将军抽车就是要通过一步跳马,在能够将军的同时将车置于马的攻击位置。
只考虑棋盘上有红帅、红车、黑马各一枚的情况,不考虑帅是否可以通过移动实现对车的保护,不考虑别马腿。 你现在写一个程序帮助你思考下,在红车和红帅不移动的情况下,3步内,黑马是否可以在不出界的情况下,实现将军抽车?如果有,将每一步的坐标
输入格式
输入共三行。
输入的第一行为两个整数 ,表示红帅的位置为 。
输入的第二行为两个整数 ,表示红车的位置为