您的位置:首页 > 其它

bfs和dfs搜索总结

2017-09-06 22:09 309 查看

1.前言

bfs和dfs的题目写了10多道,大多借助解题报告写的,自己还是没有完全掌握。希望通过这次总结能对bfs和dfs的认识更清楚一些。
bfs应该是一种层次搜索,它是通过借助队列实现的。bfs一般可以解决最优,最快情况的问题。bfs的缺点就是占用的空间太大。
dfs应该是深度搜索,类似于树的先序搜索,它是通过递归来实现的。dfs可以解决有没有解的问题,能不能走出迷宫。


2.题型

(1)八连通块问题(HDOJ1214,POJ2386)

PS:刚开始痛心疾首的WA,

一定不要轻易定义全局变量

,尽量用的时候再定义,这道题开始我把i,j定义为全局变量,一直错误。。这个最起码调了4个小时。。。痛心疾首。

HDU 1241

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
#define maxn 110
bool vis[maxn][maxn];
char mp[maxn][maxn];
int spx[]={0,1,0,-1,1,1,-1,-1};
int spy[]={1,0,-1,0,-1,1,1,-1};
int m,n;

voi
4000
d dfs(int x,int y){
vis[x][y]=true;
for(int i=0;i<8;i++){
int nx=x+spx[i];
int ny=y+spy[i];
if(nx>=0 &&nx<m &&ny>=0 &&ny<n && mp[nx][ny]=='@' &&!vis[nx][ny]){
dfs(nx,ny);
}
}

}

int main(){
while(cin>>m>>n){
int i,j;
int cnt=0;
memset(vis,false,sizeof(vis));
if(m==0&&n==0) break;
for(i=0;i<m;i++){
scanf("%s",&mp[i]);
}
for(i=0;i<m;i++){
for(j=0;j<n;j++){
if(mp[i][j]=='@'&&!vis[i][j]){
cnt++;
dfs(i,j);
}
}
}
cout<<cnt<<endl;
}
return 0;
}


(2)迷宫的最短路径BFS,并输出最短路径

http://blog.csdn.net/qq_37360631/article/details/76862479

/*POJ3984*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
#define maxn 6
#define N 5 //格子最多是5*5
bool vis[maxn][maxn];
int mp[maxn][maxn];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
struct node{
int x,y,pre;
}que[26];
int sta=0,end=1; //数组模拟队列

void print(int s){
if(que[s].pre!=-1){
print(que[s].pre);
cout<<"("<<que[s].x<<","<<que[s].y<<")"<<endl;
}
}
void bfs(int x,int y){
int k;
que[sta].pre=-1;
que[sta].x=x;
que[sta].y=y;
vis[x][y]=true;
while(sta<end){
for(k=0;k<4;k++){
int nx=que[sta].x+dir[k][0];
int ny=que[sta].y+dir[k][1];
if(nx>=0&&nx<N&&ny>=0&&ny<N&&mp[nx][ny]==0&&!vis[nx][ny]){
vis[nx][ny]=true;
que[end].pre=sta;
que[end].x=nx;
que[end].y=ny;
end++;
}
if(nx==N-1 && ny==N-1)
print(sta);
}
sta++;
}
}


(3)迷宫的最少拐弯数BFS(HDOJ1728)

http://blog.csdn.net/qq_37360631/article/details/76999765

(4)回溯法解决数字组合的问题

HDOJ1342

/*字典序输出六个升序的组合*/

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
int a[110],b[110],n;
bool vis[110];
void dfs(int num){
if(num==6){
for(int i=0;i<5;i++) cout<<b[i];
cout<<b[5]<<endl;
return ;
}
for(int i=0;i<n;i++){
if(!vis[i]&&a[i]>b[num-1]){
b[num]=a[i];
vis[i]=true;
dfs(num+1);
vis[i]=false;
}
}
}
int main(){
while(cin>>n){
memset(vis,false ,sizeof(vis));
int t;
if(t++) cout<<endl;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
dfs(0);
}
return 0;
}


HDU1016

/*素数环问题*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
int a[110],b[110],n;
bool vis[110],prime[51];
//素数打表法,打表1-n之间的素数
void init(){
int i,j;
for(i=2;i<=sqrt(50);i++){
if(prime[i]==0){  //全局变量自动初始化0
for(j=2;i*j<=50;j++){
prime[i*j]=1;
}
}
}
prime[1]=0;vis[1]=true; b[1]=1;
}

void print(){
for(int i=1;i<=n;i++)
if(i==1) cout<<b[i];
else cout<<" "<<b[i];
cout<<endl;
}
bool check(int depth){
if(depth==n+1) {
//先处理开头和最后一个数
if(prime[b[1]+b[depth-1]]==0
&&prime[b[depth-1]+b[depth-2]]==0) return true;
else return false;
}
//不是开头和最后一个数
else if(prime[b[depth-1]+b[depth-2]]==0) return true;
else return false;
}

void dfs(int depth){
if(false==check(depth)) return ;
if(depth==n+1){
print();
return ;
}
for(int i=2;i<=n;i++){
if(!vis[i]){
vis[i]=true;
b[depth]=i;
dfs(depth+1);
vis[i]=false;
}
}
}

int main(){
int t=1;
init();
while(scanf("%d",&n)!=EOF){
printf("Case %d:\n",t++);
if(1==n) cout<<"1"<<endl;
else
dfs(2);
cout<<endl;
}
return 0;
}


HDOJ1015

DFS略
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: