dfs总结
来源:互联网 发布:java json解析框架 编辑:程序博客网 时间:2024/05/22 04:49
最近在做学校出的蓝桥杯的初赛试题,发现很多题都可以用dfs暴力解决。本文将总结一下dfs常用的两种题型(全排列问题,迷宫问题),最后根据这两种题型总结出一个dfs的模版。
首先要明确一点的就是:dfs()函数的功能是解决当前应该怎么办。
对于全排列问题:当前应该解决的问题就是:当前这一位应该放什么数字进去(1~9);
对于迷宫问题:当前要解决的问题是:在当前这个点我可以往哪里走(4个方向:上下左右)。
(下面注释中带“**”的注释是重点语句)
①dfs解决全排列问题
典型题目:用数字 1~5进行全排列,显示出每一种情况并计算出总共有多少种情况。
#include <iostream>using namespace std;const int n = 5;int ans = 0;int a[n+1];int book[n] = {0}; //0 表示还没用 void bfs(int step) {if (step==n+1) // **边界条件 {ans++;//统计情况总数 for (int j=1;j<=n;j++) //显示每种可能 cout<<a[j]<<" ";cout<<endl;return; // 返回上一步 (这里的返回很重要) }for (int i=1;i<=n;i++) //**遍历所有可能的数字 {if (book[i]==0) //**判断情况是否已经处理过 { a[step] = i; //**尝试这个数字 book[i] = 1; //**把数字标记为【已尝试】 bfs(step+1); //**递归下一个位 book[i] = 0; //**尝试结束,取消标记 }}return; //返回 }int main(){bfs(1); //如果参数是 1,则边界条件为 n+1;如果是 0,边界则是 n cout<<ans<<endl;return 0;}
②dfs解决迷宫问题
题目:给出迷宫大小、迷宫简图、起点坐标,终点坐标。求到达终点的路径数和最短路径所需的步数。
#include <iostream>using namespace std;int maze[10][10]; int book[10][10] = {0}; // 标记该坐标是否走过 int dx[4] = {1,0,-1,0}; //方向 int dy[4] = {0,1,0,-1};int ans = 0; //到达终点的路线数目 int minn = 99999; // 最小步数 int m,n; // 迷宫大小int sx,sy; //起点 int gx,gy; // 终点 void dfs(int x,int y,int step){if (x==gx && y==gy) // **边界条件 {ans++; if (step < minn) minn = step;return; //返回上一步 (这里的返回很重要) }for (int k=0;k<4;k++) // **遍历所有情况(枚举 4 个方向的走法 {int nx = x + dx[k];int ny = y + dy[k];// **判断当前情况是否可用 if (0<=nx && nx<m && 0<=ny && ny<n) //判断是否有越界 {if (book[nx][ny] == 0 && maze[nx][ny] == 0) // 判断是否已经走过或者是否是障碍{book[nx][ny] = 1; //**标记这个点已经用过(走过) dfs(nx,ny,step+1); //**递归 book[nx][ny] = 0; //**尝试结束,取消这个点的标记 } }}return;}int main(){int i,j;cin>>m>>n; // 迷宫的行,列 cin>>sx>>sy>>gx>>gy; //输入起点坐标和终点坐标 for (i=0;i<m;i++)for (j=0;j<n;j++)cin>>maze[i][j];book[0][0] = 1; // (0,0)为起点,默认为已经走过dfs(sx,sy,0); //cout<<"路线数目: "<<ans<<endl;cout<<"最短路径: "<<minn<<endl; return 0;}
小结:
以上就是用dfs解决的2种常见的问题。综合打“**”的注释,我总结出dfs大致的模版:
void dfs(int step){ if (...) 边界条件 { ... return; //返回上一步(这里一定要写) } for (i=0;i<n;i++) 尝试每一种可能 { if (...) 判断当前可能是否可用 { ... book[i] = 1; //标记这个可能已经尝试 dfs(step+1); //继续下一步 book[i] = 0; //尝试结束,取消该点的标记(这里一定要写) } } return;}
其中具体问题具体分析。例如:
“尝试每一种可能”的那个for循环,如果是全排列问题,对于每一个位所填入的数字有 1~9 这9种情况,所以用一个for循环遍历1~9即可;但是如果是对于迷宫问题,对于每一步有4个方向可以走,所以除了要用for循环(0~3),还要用一个二维的“方向数组”dx,dy来辅助才能把4个方向这4种情况表现出来。
“判断当前可能是否可用”的那个if判断中,除了判断标记数组book之外,在迷宫问题中还要注意判断“该点的坐标是否越界”、“该点是否是障碍”等问题。
2 0
- dfs总结
- DFS 总结
- dfs总结
- dfs总结
- DFS总结
- 7.29 DFS总结
- DFS,BFS算法总结
- dfs学习总结
- BFS与DFS总结
- 总结之bfs,dfs
- dfs简单总结
- Dijkstra+DFS模板总结
- DFS学习归纳总结
- DFS序总结
- DFS BFS 搜索总结
- DFS-lintcode解法总结
- DFS个人总结
- 数据结构总结之dfs
- 移动APP开发周期中各个阶段的问题和解决工具
- jar包 包名修改
- Android设计模式解析(一)
- 基于memcache的远程缓存工具类
- POI 设置单元格背景颜色
- dfs总结
- 设计原则之迪米特法则
- 知识随笔
- Aptana Studio 3快捷键
- Python连接MySQL数据库locahost无法连接的问题
- JavaScript学习之路--面向对象设计之创建对象(2)--原型对象详解
- jquery事件命名空间
- 搭积木
- Web网站的几个并发量级