4th day
BFS和DFS专题(今天的老哥讲的老仔细了,之前看这个都看不懂做了题目之后感觉确实有点入门的感觉)
贴一个大佬的整理:https://www.cnblogs.com/aiguona/p/7268667.html
下面是来自大佬博客的深搜广搜的模板
三、模板
1.深搜
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
char map[1000][1000];//用来存储图的信息
/*标记是否搜索过,本题目没有使用,因为是一次访问,直接将访问过的修改即可*/
int logo[1000][1000];
int m,n,sum;
/*表示八个方向,四个方向时,将后面四组删掉就可以了*/
int dir[8][2]= {0,1, 0,-1, 1,0, -1,0, 1,1, 1,-1, -1,1, -1,-1};
void DFS(int x,int y)
{
if(x>=0&&y>=0&&x<n&&y<m)//这里是判断是否越界,根据题目要求改写
{
if(map[x][y]=='W')//如果符合条件就继续递归。
{
map[x][y]='.';//标记为‘.’防止多次访问
for(int i=0; i<8; i++)//因为八个方向,所以循环八次。
DFS(x+dir[i][0],y+dir[i][1]);
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
sum=0;
memset(logo,0,sizeof(map));
getchar();
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
cin>>map[i][j];
}
getchar();
}
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
if(map[i][j]=='W')
{
DFS(i,j);
sum++;//计数
}
}
cout<<sum<<endl;
}
}
2.广搜
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define MAX 0x3f3f3f3f
using namespace std;
int map[305][305];//存节点信息
int vis[305][305];//标记数组
int dir[4][2]= {-1,0, 1,0, 0,1, 0,-1};//上下左右四个方向
int end;
struct node
{
int x,y;//两点表示节点位置
int time;
} start;//入队列使用
queue<node> q;//队列,自己维护用来存储节点信息
int bfs(int x,int y)
{
memset(vis,0,sizeof(vis));
start.x=x,start.y=y,start.time=0;//将传递过来的0.0节点放入结构体
vis[x][y]=1;//标记为已搜过
q.push(start);//入队列
while(!q.empty())
{
node now=q.front();//取队头元素
q.pop();
if(map[now.x][now.y]==MAX)
{
return now.time;//如果符合条件,返回;根据题意自己写符合的条件。
}
for(int i=0; i<4; i++)//四个方向入队列
{
start.x=now.x+dir[i][0],start.y=now.y+dir[i][1];//将第一个方向的入队列
start.time=now.time+1;
if(start.x>=0&&start.y>=0&&vis[start.x][start.y]==0&&start.time<map[start.x][start.y])//判断是否越界
{
vis[start.x][start.y]=1;
q.push(start);
}
}
}
return -1;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(map,MAX,sizeof(map));
for(int j=0; j<n; j++)
{
int x,y,time;
scanf("%d%d%d",&x,&y,&time);
if(map[x][y]>time)
map[x][y]=time;
for(int i=0; i<4; i++)//自己建图过程,一般不需要自己建图
{
int cx,cy;
cx=x+dir[i][0],cy=y+dir[i][1];
if(cx>=0&&cy>=0)
if(map[cx][cy]>time)
map[cx][cy]=time;
}
}
int ans=bfs(0,0);//从00点开始广搜,根据题目要求具体定
cout<<ans<<endl;
}
}
根据今天的题目,深搜广搜各有自己不同的用法,广搜在找最短路径上面很有用处,但是相对来说空间复杂度较高//
B - Dungeon Master(hdu)
这道题目是一道三维的广搜,是bfs的典型模板题,这里其实为将来处理多维的提供了一个结构体的思路(之前学长使用pair去连接两个数,而用struct也可以,总之只要把他们连起来就可以了)
注意点主要是在输入问题还有临界的判断条件上,这是两个易错点
贴一下自己写的代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <queue>
using namespace std;
typedef struct
{
int a,b,c;
}node;
const int inf=0x3f3f3f3f;
char mp[35][35][35];//存储地图
int tx[10]={0,1,-1,0,0,0,0};
int ty[10]={0,0,0,1,-1,0,0};
int tz[10]={0,0,0,0,0,1,-1};//人物移动的方向
int dis[35][35][35];//到出口的距离,类比时间
int px,py,pz,fx,fy,fz;
int l,r,c;
void bfs()
{
node pos;
pos.a=px,pos.b=py,pos.c=pz;
queue<node>q;
q.push(pos);
dis[px][py][pz]=0;
while(!q.empty())
{
int x=q.front().a,y=q.front().b,z=q.front().c;
q.pop();
for(int i=1;i<=6;i++)
{
int xx=x+tx[i],yy=y+ty[i],zz=z+tz[i];
if(xx>=0&&xx<=l-1&&yy>=0&&yy<=r-1&&zz>=0&&zz<=c-1&&dis[xx][yy][zz]==inf&&mp[xx][yy][zz]!='#')
{
dis[xx][yy][zz]=dis[x][y][z]+1;
node pu;
pu.a=xx,pu.b=yy,pu.c=zz;
q.push(pu);
}
}
}
}
int main()
{
char hc;
while(scanf("%d %d %d",&l,&r,&c)!=EOF)
{
memset(dis,inf,sizeof(dis));
if(l==0&&r==0&&c==0)
{
break;
}
for(int i=0;i<l;i++)
{
for(int j=0;j<r;j++)
{
scanf("%s",mp[i][j]);
//printf("%s\n",mp[i][j]);
for(int k=0;k<c;k++)
{
if(mp[i][j][k]=='S')
{
px=i;
py=j;
pz=k;
}
if(mp[i][j][k]=='E')
{
fx=i;
fy=j;
fz=k;
}
}
}
} //找初始位置
bfs();
int ans=dis[fx][fy][fz];
//printf("%d\n",dis[fx-1][fy][fz]);
if(ans==inf)
{
printf("Trapped!\n");
}
else
{
printf("Escaped in %d minute(s).\n",ans);
}
}
return 0;
}
这个其实我觉得特别有代表,在bfs的水题当中
dfs现在目前还是只做了n皇后那题,思路就是遍历判断每一个位置行不行,最后存储下来,但是dfs还缺少一定的理解(明天需要好好看看,摸点内容追上那帮大佬)
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stdlib.h>
#include <iostream>
#include <string.h>
int sum=0;
int a[11]={0};
int flag=1;
int t,i;
void dfs(int n)
{
if(n==t+1)
{
sum++;
return ;
}
for(int i=1;i<=t;i++)
{
flag=1;
a[n]=i;//第n个皇后所在的列数
for(int j=1;j<n;j++)
{
if(a[j]==i||(abs(j-n)==abs(a[j]-i)))//判断是否同列、主对角线,副对角线
{
flag=0;
break;
}
}
if(flag==1)
{
//a[i]=0;
dfs(n+1);
}
}
}
int main()
{
int u;
int ans[20]={0};
for(i=1;i<=10;i++)
{
memset(a,0,sizeof a);
sum=0;
t=i;
dfs(1);
ans[i]=sum;
}
while(scanf("%d",&u)!=EOF)
{
if(u==0)
{
break;
}
printf("%d\n",ans[u]);
}
return 0;
}


浙公网安备 33010602011771号