BFS(9)
2020-02-02 19:45
246 查看
BFS(这篇东西主要靠大家慢慢理解感受)
前面陆陆续续的讲的都是一些很基础很容易的算法,这篇讲的东西真的是有点难了,并不是板子的问题,而是因为他太抽象了,全靠读者自己想象力。可能是小编的水平不够,真的是有种只可意会不可言传的感觉,不过小编还是尽力为大家讲清楚这个BFS。注:有一些基础的东西读者直接百度吧,没必要讲。
再补充一点,BFS和DFS就是遍历图的俩种方法,他的目的很明确,就是在图中找一些东西。
传送门: Red and Black HDU - 1312
小编在这用一种别的思路:先把所有位置都放成#,然后遇见#不能走,走过的点变成#。另外的一种方法就是再开一个二维数组,把走过的点记成1,没走的记成0(后面会用到,简单,到时候读者再理解)
也没有一个确切的板子,直接看下面的这个板子题吧
//#include <bits/stdc++.h> #include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; typedef long long ll; int x,y,x1,y11; char c[30][30]; int dx[4]={-1,0,0,1}; int dy[4]={0,-1,1,0}; //坐标系下的四个方向 //可以写成dd[4][2]={-1,0,1,0,0,-1,0,1} ,一个意思 struct node { int x,y; }now,nt; //不要问为什么不用 next,因为next是一个已经有的函数 //now表示当前所在位置,nt表示下步可以走到的位置 int main() { while(~scanf("%d %d",&x,&y)&&x&&y) { int sum=1; memset(c,'#',sizeof(c)); //将整个图先初始化为“#”; for(int i=1;i<=y;i++) //存图,用cin,不用这么麻烦 { //用scanf这样存,注意 getchar(); getchar(); for(int j=1;j<=x;j++) { scanf("%c",&c[i][j]); if(c[i][j]=='@') { x1=i; y11=j; //找见入口 入口标记下来 } } } queue<node> q; now.x=x1; now.y=y11; q.push(now); //把现在所在位置压入队列 c[x1][y11]='#'; //走过的路变成# while(!q.empty()) { now=q.front(); //从这个点开始走 for(int i=0;i<4;i++) //四个方向 { nt.x=now.x+dx[i]; nt.y=now.y+dy[i]; //表示向哪个方向走 if(c[nt.x][nt.y]!='#') //如果下个坐标没走过,就进去 { sum++; c[nt.x][nt.y]='#'; //走过的点变成# q.push(nt); //把能到达的坐标都压入队列里面 } } q.pop(); // 当前的这个坐标从队列中弹出去 } printf("%d\n",sum); } return 0; }
传送门:Rescue HDU - 1242
换种写法,不过思路一样。这种写法更为常见,但是有点麻烦。(具体的代码自己看吧,和上题基本一样,就是表达方式不同)
#include<bits/stdc++.h> using namespace std; typedef long long ll; int n,m,x,y,x_1,x2,y_1,y2;; //该死的编译器定义不了y1。。。 char a[205][205]; //存图 int b[205][205]; //用来记录是否走过,走过就赋值为1 ,否则就是0 int d[4][2]={-1,0,1,0,0,1,0,-1}; //注意这种表达方式。 struct node { int x,y,step; friend bool operator < (node a,node b) { return a.step>b.step; } }now,nt; int BFS() { priority_queue <node> q; now.x=x2; now.y=y2; now.step=0; q.push(now); while(!q.empty()) { now=q.top(); q.pop(); x=now.x; y=now.y; if(x==x_1&&y==y_1) return now.step; b[x][y]=1; for(int i=0;i<4;i++) { x=now.x+d[i][0]; y=now.y+d[i][1]; if(x>0&&y>0&&x<=n&&y<=m&&b[x][y]==0&&a[x][y]!='#') { nt.x=x; nt.y=y; nt.step=now.step+1; if(a[x][y]=='x') nt.step++; q.push(nt); } } } return 0; } int main() { ios::sync_with_stdio(false); while(cin>>n>>m) //行列 { int s=0; memset(b,0,sizeof b); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a[i][j]; if(a[i][j]=='a') { x_1=i; y_1=j; } if(a[i][j]=='r') { x2=i; y2=j; b[i][j]=1; } } } s=BFS(); if(s) cout<<s<<endl; else cout<<"Poor ANGEL has to stay in the prison all his life."<<endl; } return 0; }
看了俩个平面的,看一个立体的逃生题
传送门: Dungeon Master POJ - 2251
(思路还是一模一样,大家自己看吧)
#include<iostream> #include<queue> #include<cstdio> #include<string> #include<cstring> using namespace std; char c[50][50][50]; int l,m,n,x1,y1,z1; int dd[6][3]={{-1,0,0},{0,-1,0},{0,0,-1},{1,0,0},{0,1,0},{0,0,1}}; struct node { int x; int y; int z; int time; friend bool operator < (node a,node b) { return a.time >b.time; } }now,next; int BFS() { int ans=0; priority_queue<node> q; now.x=x1; now.y=y1; now.z=z1; now.time=0; q.push(now); c[x1][y1][z1]='#'; while(!q.empty()) { now=q.top(); for(int i=0;i<6;i++) { next.x=now.x+dd[i][0]; next.y=now.y+dd[i][1]; next.z=now.z+dd[i][2]; next.time=now.time+1; if(c[next.x][next.y][next.z]!='#') { if(c[next.x][next.y][next.z]=='E') { //next.time++; ans=next.time; break; } c[next.x][next.y][next.z]='#'; q.push(next); } } q.pop(); } return ans; } int main() { while(~scanf("%d%d%d",&l,&m,&n)&&l&&m&&n) { memset(c,'#',sizeof(c)); for(int i=1;i<=l;i++) { for(int j=1;j<=m;j++) { for(int k=1;k<=n;k++) { cin>>c[i][j][k]; if(c[i][j][k]=='S') { x1=i; y1=j; z1=k; } } } } int ss=BFS(); if(ss) printf("Escaped in %d minute(s).\n",ss); else printf("Trapped!\n"); } return 0; }
传送门:Catch That Cow POJ - 3278
(一模一样的题,提供一个代码)
//#include <bits/stdc++.h> #include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; typedef long long ll; struct node { int x,step; }a,next; int main() { int n,k; while(~scanf("%d %d",&n,&k)) { int ans=0; int vis[100010]; queue<node> q; memset(vis,0,sizeof(vis)); a.x=n; a.step=0; vis[n]=1; q.push(a); while(!q.empty()) { a=q.front(); if(a.x==k) { ans=a.step; break; } else { if(a.x*2<=100000&&!vis[a.x*2]) { vis[a.x*2]=1; next.x=a.x*2; next.step=a.step+1; q.push(next); } if(a.x+1<=100000&&!vis[a.x+1]) { vis[a.x+1]=1; next.x=a.x+1; next.step=a.step+1; q.push(next); } if(a.x-1<=100000&&!vis[a.x-1]) { vis[a.x-1]=1; next.x=a.x-1; next.step=a.step+1; q.push(next); } q.pop(); } } printf("%d\n",ans); } return 0; }
传送门:Battle City POJ - 2312
(都是一模一样的代码,建议做做,就当练手)
#include<iostream> #include<queue> #include<cstdio> #include<string> #include<cstring> using namespace std; const int INF=0x3f3f3f3f; const int maxn=305; int n, m, sx, sy, ex, ey; char mp[maxn][maxn]; bool vis[maxn][maxn]; int dir[4][2]={{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; struct node{ int x, y, steps; bool operator < (const node &tmp) const { return steps>tmp.steps; } }; int BFS(){ memset(vis, false, sizeof(vis)); priority_queue<node> q; q.push((node){sx, sy, 0}); vis[sx][sy]=true; while(q.size()) { node tmp; tmp=q.top(); q.pop(); if(tmp.x==ex && tmp.y==ey) { return tmp.steps; } for(int i=0; i<4; i++) { int tx=tmp.x+dir[i][0]; int ty=tmp.y+dir[i][1]; if(tx<0 || tx>=n || ty<0 || ty>=m) continue; if((mp[tx][ty]=='E'||mp[tx][ty]=='T') && vis[tx][ty]==false) { q.push((node){tx, ty, tmp.steps+1}); vis[tx][ty]=true; } else if(mp[tx][ty]=='B' && vis[tx][ty]==false) { q.push((node){tx, ty, tmp.steps+2}); vis[tx][ty]=true; } } } return -1; } int main(){ while(~scanf("%d%d", &n, &m) && (n||m)) { for(int i=0; i<n; i++) { scanf("%s", mp+i); for(int j=0; j<m; j++) { if(mp[i][j]=='Y') { sx=i; sy=j; } else if(mp[i][j]=='T') { ex=i; ey=j; } } } printf("%d\n", BFS()); } return 0; }
传送门:Knight Moves HDU - 1372
#include<bits/stdc++.h> using namespace std; typedef long long ll; int dd[8][2]= {{1,-2},{2,-1},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2}}; int x_1,y_1,x2,y2; int c[100][100]; //用来标记走过的点 struct node { int x,y,step; friend bool operator < (node a,node b) { return a.step>b.step; } }now,nt; int BFS() { memset(c,0,sizeof c); c[x_1][y_1]=1; priority_queue<node> q; now.x=x_1; now.y=y_1; now.step=0; q.push(now); while(!q.empty()) { now=q.top(); if(now.x==x2&&now.y==y2) return now.step; for(int i=0;i<8;i++) { nt.x=now.x+dd[i][0]; nt.y=now.y+dd[i][1]; if(nt.x>0&&nt.x<=8&&nt.y>0&&nt.y<=8&&c[nt.x][nt.y]==0) { nt.step=now.step+1; q.push(nt); c[nt.x][nt.y]=1; } } q.pop(); } return 0; } int main() { char a[3],b[3]; while(~scanf("%s %s",&a,&b)) { x_1=a[0]-'a'+1; y_1=a[1]-'0'; x2=b[0]-'a'+1; y2=b[1]-'0'; printf("To get from %s to %s takes %d knight moves.\n",a,b,BFS()); } return 0; }
传送门:Robot Motion POJ - 1573 (特有意思,涉及新方法)
很有意思的一个题,做了半天没做出来,最后百度了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[12][12]; int vis[12][12]; int main() { int a,b,c; while(scanf("%d %d %d",&a,&b,&c)) { memset(vis,0,sizeof(vis)); if(a==0&&b==0&&c==0) break; for(int i=0;i<a;i++) for(int j=0;j<b;j++) cin>>s[i][j]; int x=0,y=c-1,step=0; while(true) { step++; if(s[x][y]=='N'&&!vis[x][y]) { vis[x][y]=step; x--; } else if(s[x][y]=='S'&&!vis[x][y]) { vis[x][y]=step; x++; } else if(s[x][y]=='W'&&!vis[x][y]) { vis[x][y]=step; y--; } else if(s[x][y]=='E'&&!vis[x][y]) { vis[x][y]=step; y++; } if(x<0||x==a||y<0||y==b) { printf("%d step(s) to exit\n",step); break; } else if(vis[x][y]) { printf("%d step(s) before a loop of %d step(s)\n",vis[x][y]-1,step+1-vis[x][y]); break; } } } }
传送门: Number Transformation LightOJ - 1141
我的天,差点没看懂题。给你一个整数A和B,A可以加上自己本身的质因数(不包括1和本身)【这点很重要】,从而等于B,问A通过加的操作的最少次数。
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<cmath> using namespace std; const int maxn = 2005; int p[2005]; int vis[2005]; void init() { p[1]=p[0]=1; for(int i=2;i<sqrt(maxn);i++) { for(int j=i*2;j<maxn;j+=i) p[j]=1; } } struct node{ int x,step; }; int flag; void bfs(int x,int y) { memset(vis,0,sizeof(vis)); flag=-1; queue<node> q; node now,mid; now.x=x;now.step=0; vis[x]=1; q.push(now); int ans=-1; while(!q.empty()) { now=q.front(); q.pop(); for(int i=2;i<now.x;i++) { if(now.x%i==0&&!p[i]) { mid.x=now.x+i; if(vis[mid.x]||mid.x>y) continue; vis[mid.x]=1; mid.step=now.step+1; if(mid.x==y) { flag=mid.step; return ; } q.push(mid); } } } } int main() { int n,a,b; cin>>n; init(); int cnt=1; while(n--) { int a,b; cin>>a>>b; cout<<"Case "<<cnt++<<": "; if(a==b) { puts("0"); continue; } bfs(a,b); cout<<flag<<endl; } }
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- HDU - 1495 非常可乐 bfs互倒三杯水
- hdu 2128(bfs)
- uva12112 - Iceman BFS模拟 启发式搜索
- [kuangbin带你飞]专题二 搜索进阶 A(康拓展开+bfs)
- 连连看-广搜bfs
- 迷宫问题bfs+打印路径
- 【BFS+优先级队列】Rescue
- hdu 1026 Ignatius and the Princess I(bfs+priority_queue)
- USACO Jan08 (COGS 174) 架设电话线 二分答案,缩点,BFS判断可行性
- FZU2150 Fire Game (BFS)
- 树的BFS
- dfs与bfs
- HPU DFS + BFS 专项练习A - Red and Black HDU - 1312
- POJ 1475 Pushing Boxes 搜索- 两重BFS
- hdu1242 Rescue(BFS)
- CSU-ACM2017暑期训练6-bfs H - ACM小组的古怪象棋 CSU - 1224
- POJ 3322 Bloxorz I (bfs+辅助数组+状态压缩+自己的一些搜索理解)
- hdu 4707 Pet【BFS求树的深度】
- 迷宫问题、最短路(BFS,DFS)
- poj2049(bfs) Finding Nemo