赞
踩
这篇原本是两个搜索算法,但是发现BFS那个单独看的人多,所以这篇改为单独的DFS,建议先看完BFS
深度优先搜索算法是最简便的图的搜索算法之一。其别名又叫DFS,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次,但在类似迷宫的问题中效率较低。
还是以好理解的迷宫举例子
0是路,1是墙,2是入口,3是出口
0 0 1 0 1
2 1 0 0 3
0 0 0 1 0
0 1 0 1 0
0 1 0 0 0
也就是
把走过的路标记为2
那么来看下DFS是怎么走的
开始上图
从起点一个方向走到头
死路,那么后退直到有别的方向
继续
那么你可能就会问了,这不对啊,最短路明明是走上面啊
别急,这就是它走迷宫效率不高的原因,他有很多种走到终点的方法,但是不一定是最快的,这有时候取决于你的方向设定,也许某个顺序你就能蒙到最短路,但往往没这可能,所以我们可以让他把所有路走一遍,比较出那个最短的
DFS的精髓就在于return,利用好递归以及条件的判定
上面问题的代码(到了就行,不一定最短)
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; int m,n,sum=0,ok=1; //看下面 int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; //看我!看我!看我!方向可以自己改改看有什么效果 int Map[5][5]; //看过了,回上面 int l,t=0; vector<pair<int,int> > q; bool judge(int x1,int y1){//判边界 return (x1>=0&&x1<=4&&y1>=0&&y1<=4&&(Map[x1][y1]==0||Map[x1][y1]==3)); } void dfs(int x,int y){ if(ok)//到了就不跑了,后面全过 return; for(int i=0;i<4;i++){ int x1 = x+dir[i][0]; int y1 = y+dir[i][1]; if(judge(x1,y1)){ if(Map[x1][y1]==3){ //到终点 ok=1; cout << sum<<endl; return; } Map[x1][y1]=2; for(int i=0; i<5; i++){ //打印地图 for(int j=0; j<5; j++) cout << Map[i][j]; cout << endl; } cout << endl; pair<int,int> z(x1,y1); q.push_back(z); sum++; dfs(x1,y1); if(ok) return; Map[x1][y1]=0; for(int i=0; i<5; i++){ //打印地图 for(int j=0; j<5; j++) cout << Map[i][j]; cout << endl; } cout << endl; q.pop_back(); sum--; } } } int main() { int sx,sy; ok = 0; for(int i=0;i<=4;i++){ for(int j=0;j<=4;j++){ cin>>Map[i][j]; if(Map[i][j]==2){ sx = i; sy = j; } } } pair<int,int> z(sx,sy); q.push_back(z); dfs(sx,sy); return 0; }
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; int m,n; int vis[5][5]; int f[4][2] = {{0,-1},{-1,0},{0,1},{1,0}}; int a[5][5]; int l,t=0; vector<pair<int,int> > q; vector<pair<int,int> > q2; bool judge(int x1,int y1){ return (x1>=0&&x1<=4&&y1>=0&&y1<=4&&vis[x1][y1]==0&&a[x1][y1]==0); } void dfs(int x,int y){ if(x == 4&&y== 4){ if(t==0|| q2.size()>q.size()){ t = 1; l = q.size(); q2.clear(); for(int i=0;i<q.size();i++){ q2.push_back(q[i]); } } return ; } for(int i=0;i<4;i++){ int x1 = x+f[i][0]; int y1 = y+f[i][1]; if(judge(x1,y1)){ vis[x1][y1]=1; pair<int,int> z(x1,y1); q.push_back(z); dfs(x1,y1); vis[x1][y1]=0; q.pop_back(); } } } int main() { memset(a,0,sizeof a); memset(vis,0,sizeof vis); for(int i=0;i<=4;i++){ for(int j=0;j<=4;j++){ cin>>a[i][j]; } } vis[0][0]=1; pair<int,int> z(0,0); q.push_back(z); dfs(0,0); for(int i=0;i<l;i++){ cout << "(" << q2[i].first << ", " << q2[i].second << ")"; if(i!=l-1) cout << endl; } return 0; }
那么问题又来了,既然这样我为什么要用麻烦的DFS?
这是因为BFS由于同步走,也就意味着同步存储,当数据量过大时,占用的空间将是很大的量,一些题是会超内存的。(聪明反被聪明误?)同样道理,DFS相当于遍历,因此总是会超时间。(太耿直了也不行啊)
依旧简单的一题!
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; int m,n,p; int a[10][10]; int b[10][10]; int vis[10][10]; int f[8][2] = {{-2,-1},{-2,1},{-1,2},{1,2},2,1,2,-1,1,-2,-1,-2}; vector<pair<int,int> > q; int xb,yb,xe,ye,sum=0; bool judge(int x1,int y1){ return (x1>=0&&x1<m&&y1>=0&&y1<n&&vis[x1][y1]==0); } void dfs(int x,int y){ // cout<<"x1: "<<x<<" y1:"<<y<<endl; p=1; for(int i=0;i<m;i++) { for(int l=0;l<n;l++) { if(vis[i][l]==0) { p=0; break; break; } } } if(p){ sum++; return ; } for(int i=0;i<8;i++){ int x1 = x+f[i][0]; int y1 = y+f[i][1]; if(judge(x1,y1)){ vis[x1][y1]=1; pair<int,int> z(x1,y1); q.push_back(z); dfs(x1,y1); vis[x1][y1]=0; q.pop_back(); } } } int main() { int o; cin >> o; while(o--){ sum = 0; memset(vis,0,sizeof (vis)); cin>>m>>n; cin>>xb>>yb; vis[xb][yb]=1; pair<int,int> z(xb,yb); q.push_back(z); dfs(xb,yb); cout << sum << endl; } return 0; }
貌似是计蒜客的,大概复述一下,你可以自己造点数据
给你一串字符,输出变化后的样子,给几个例子(不保证完全和原题一样,只能说差不多)
3(h)->hhh
2(2(a)b)->2(aab)->aabaab
b1(2(an)a)->banana
你可以自己搞更多重,我偷个懒 ̄ω ̄=
之前说过这个玩意时间复杂度会很高,那么一个很必要的技巧就是剪枝,也就是提前结束无用过程,祝你时间达标hhh
题目链接
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; int m,n; int vis[100][100]; int f[4][2] = {{0,-1},{-1,0},{0,1},{1,0}}; string b,a[100]; int t,flag; int xs,ys,xl,yl; vector<pair<int,int> > q; bool judge(int x1,int y1){ return (x1>=0&&x1<m&&y1>=0&&y1<n&&vis[x1][y1]==0&&a[x1][y1]!='X'); } void dfs(int x,int y,int l){ if(flag) return; if(x == xl&&y== yl){ if(l==t){ flag=1; } return ; } if(abs(x-xl)+abs(y-yl)+l>t || (t-l-abs(x-xl)-abs(y-yl))%2) return; for(int i=0;i<4;i++){ int x1 = x+f[i][0]; int y1 = y+f[i][1]; if(judge(x1,y1)){ vis[x1][y1]=1; dfs(x1,y1,l+1); vis[x1][y1]=0; } } } int main() { while(cin >> m >> n >> t) { if(m==0) return 0; flag = 0; for(int i=0;i<m;i++) { cin >> a[i]; for(int j=0;j<n;j++) { if(a[i][j]=='S'){ xs=i; ys=j; }else if(a[i][j]=='D'){ xl=i; yl=j; } } } memset(vis,0,sizeof vis); vis[xs][ys]=1; dfs(xs,ys,0); if(flag) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
除了地图,我们还可以应用到别的方面
题目链接
#include <iostream> #include <algorithm> #include <cstring> using namespace std; int n,sum,l,flag=0; int a[65]; int vis[65]; void dfs(int m,int l2){ //个数,缺少长度 if(flag) return; if(m==0 && l2==0) { flag=1; } if(flag) return; if(l2==0) l2 = l; for(int i=0;i<n;i++) { if(!vis[i] && a[i]<=l2) { if(i>0) { if(!vis[i-1]&&a[i]==a[i-1]) continue; } vis[i]=1; dfs(m-1,l2-a[i]); vis[i]=0; if(a[i]==l2||l2==l) return; } } return; } bool cmp(int a,int b) { return a>b; } int main() { while(cin >> n && n!=0) { flag=0; sum=0; for(int i=0;i<n;++i) { cin >> a[i]; sum+=a[i]; } sort(a,a+n,cmp); for(l=a[0];l<=sum/2;++l) { if(sum%l) continue; memset(vis,0,sizeof(vis)); dfs(n,l); if(flag) { cout << l << endl; break; } } if(l>sum/2) cout << sum << endl; } return 0; }
dfs就是刚,不撞三个墙不回头!
这里仅仅从算法的角度去观察,所以不要忘了别的基础理论a
天坑补完ヽ(°▽、°)ノ好耶!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。