题目传送门:P1605 迷宫
前言
dfs迷宫题,是一道很好的练手模板题
这道题一定要回溯!回溯!!
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,t;
int sx,sy,fx,fy;
int lx,ly;
int a[10][10]={0},ans=0;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
void dfs(int x,int y){if(x==fx&&y==fy){ans++;return;}for(int i=0;i<4;i++){int nx=x+dx[i];int ny=y+dy[i];if(nx<1||ny<1||nx>n||ny>m||a[nx][ny]==1)continue;a[nx][ny]=1;dfs(nx,ny);a[nx][ny]=0;}
}
int main(){ios::sync_with_stdio(false);cin>>n>>m>>t;cin>>sx>>sy>>fx>>fy;while(t--){cin>>lx>>ly;a[lx][ly]=1;}a[sx][sy]=1;dfs(sx,sy);printf("%d",ans);return 0;
}
解析
这道题有两个坑点,不把这两个坑点过了就过不了40分这一关。
1. 起点要标记上是已经走过的路
2. 一定要回溯!!!回溯!!!!!!
看一看心路历程:
02-21 20:33:55
这是第一次提交,是行云流水的敲完代码直接交的,只得了40分。
看看非ac代码(40pts):
#include<bits/stdc++.h>
using namespace std;
int n,m,t;
int sx,sy,fx,fy;
int lx[15],ly[15];
int a[10][10]={0},ans=0;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
bool flag=true;
void dfs(int x,int y){if(x==fx&&y==fy){ans++;return;}for(int i=0;i<4;i++){int nx=x+dx[i];int ny=y+dy[i];if(nx<1||ny<1||nx>m||ny>n||a[nx][ny]==1)continue;/*for(int i=0;i<t;i++){if(nx==lx[i]&&ny==ly[i]){flag=false;break;}}*/if(!flag)continue;a[nx][ny]=1;dfs(nx,ny);}
}
int main(){ios::sync_with_stdio(false);cin>>n>>m>>t;cin>>sx>>sy>>fx>>fy;for(int i=0;i<t;i++){cin>>lx[i]>>ly[i];a[lx[i]][ly[i]]=1;}dfs(sx,sy);printf("%d",ans);return 0;
}
//这里原点没有标记,也没有回溯
没有这两点,有其中一点也是40分,缺一不可。
然后就经历了:
期间一直在改,却一直没有加回溯。
就在想看题解时,就先下载了#2的数据:
???
于是,我就用我的代码交上去一看:
“1”?
这就有可能是没有删除标记的问题了!
于是加上a[nx][ny]=0;一看:
对了,其实就是回溯的问题。
加上去:
ok,ac了。
花了将近1个小时来调这道题,那就给大家放一个有注释的程序把....
#include<bits/stdc++.h>
using namespace std; int n, m, t; // 定义变量n, m分别表示网格的行数和列数,t表示要标记的障碍物数量
int sx, sy, fx, fy; // 定义起点和终点的坐标
int lx, ly; // 定义临时变量,用于读入障碍物的坐标
int a[10][10] = {0}; // 定义一个10x10的网格,并初始化为0(可通行)
int ans = 0; // 定义变量ans,用于记录从起点到终点的路径数量 int dx[4] = {0, 0, -1, 1}; // 定义水平方向上的移动增量
int dy[4] = {1, -1, 0, 0}; // 定义垂直方向上的移动增量 // DFS函数,用于从当前位置(x, y)开始搜索到达终点的路径数量
void dfs(int x, int y) { if (x == fx && y == fy) { // 如果当前位置是终点 ans++; // 路径数量加1 return; // 返回上一层递归 } for (int i = 0; i < 4; i++) { // 遍历四个方向 int nx = x + dx[i]; // 计算下一个位置的x坐标 int ny = y + dy[i]; // 计算下一个位置的y坐标 if (nx < 1 || ny < 1 || nx > n || ny > m || a[nx][ny] == 1) continue; // 如果下一个位置越界或已被标记为障碍物,则跳过 a[nx][ny] = 1; // 将下一个位置标记为已访问 dfs(nx, ny); // 递归访问下一个位置 a[nx][ny] = 0; // ←←←←←←←就是这个!!!一定要回溯!!!}
} int main() { ios::sync_with_stdio(false); // 关闭C++标准输入输出流与C标准输入输出流的同步,以提高效率 cin >> n >> m >> t; // 读入网格的行数、列数和障碍物的数量 cin >> sx >> sy >> fx >> fy; // 读入起点和终点的坐标 while (t--) { // 循环t次,读入障碍物的坐标 cin >> lx >> ly; // 读入障碍物的坐标 a[lx][ly] = 1; // 将障碍物位置标记为1(不可通行) } a[sx][sy] = 1; // ←←←←←←←←这个也要加!!!dfs(sx, sy); // 从起点开始进行深度优先搜索 printf("%d", ans); // 输出从起点到终点的路径数量 return 0; // 程序正常结束
}
The end.