bfs题目小结

本文精选了多个BFS算法的经典题目及其解决方案,包括基础BFS、三维BFS、BFS结合优先队列等,覆盖HDOJ平台上的典型题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处,谢谢   http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

刚好yobobobo最近做BFS,我也被渲染了,当是复习一下,也总结一下吧,大部分是HDOJ上的BFS题目,由于本人时间有限,会持续更新


HDU 1548 http://acm.hdu.edu.cn/showproblem.php?pid=1548

基础的BFS,每次有两个方向,分别把步数乘以1和-1就行了。其余的都是基础BFS,注意下起点终点重合的情况


HDU 1372http://acm.hdu.edu.cn/showproblem.php?pid=1372

经典的马步移动,基本的BFS改成8个方向,同样处理即可


HDU 2717 http://acm.hdu.edu.cn/showproblem.php?pid=2717

3种情况移动,+1,-1,*2,没啥好说的,同样处理就行了,同时注意下边界,比目标大的话就只能全部-1,如果比目标大了就没必要*2


HDU 3766 http://acm.hdu.edu.cn/showproblem.php?pid=3766

比较坑,开始以为和1372一样,其实不是,这题没有给出范围,但是范围很大,之前需要逼近下,然后再搜索,或者直接枚举判断下就行了


HDU 1026 http://acm.hdu.edu.cn/showproblem.php?pid=1026

其实做法一样,需要打怪耗时,需要用优先队列或者最小堆来处理下,不过这题比较纠结的是需要输出路径,首先注意细节问题,之前用的是next,保存后继结点,果断被坑,一个点在搜索的时候的后继结点会有好多,果断改成pre,前趋表示。


HDU 1072 http://acm.hdu.edu.cn/showproblem.php?pid=1072

题目总体思路很明确,遇到数字4的话,时间重置下,在判重的时候需要用三维数组,加一个当前时间,如果两次到某点剩余时间相同,那就没必要再走了。


HDU 1175 http://acm.hdu.edu.cn/showproblem.php?pid=1175

弱爆了,果断也被坑了,开始觉得只要保存某个结点的方向和已拐的弯,然后搜索就行了,其实只要沿某条直线先一直搜到底就行了,不过还是要保存方向和已拐的弯的个数。


HDU 1180 http://acm.hdu.edu.cn/showproblem.php?pid=1180

注意下楼梯部分的细节问题就行了,可以停在原地等待楼梯转向,这里比较坑啊,而且楼梯处不需要标记,可能两个方向都要走


HDU 1242 http://acm.hdu.edu.cn/showproblem.php?pid=1242

果断BFS+优先队列


HDU 1728 http://acm.hdu.edu.cn/showproblem.php?pid=1728

类似于连连看,限制了拐弯次数,只需要每个方向走到底就行了,题目输入有些坑,行列有点混乱应注意。而且如果之前搜过的点,之后不能停止而是跳过。


HDU 2579 http://acm.hdu.edu.cn/showproblem.php?pid=2579

由于 在K的倍数的时候石头会消失,所以不能像其它迷宫问题一样判重,可能当前时间石头还在,而走一圈再回来石头消失,也许就有其它的路径可以走,因此判断的时候要加上三维数组flag[x][y][time%k],如果到某点的时间取余都相同,那么此时的状态就是完全相同,没有意义的

 

HDU 2012 http://acm.hdu.edu.cn/showproblem.php?pid=2102
三维的BFS,注意一些细节就行了,譬如进入传送门就必须传送,而且另一边必须只有是空地才行,坑死了,读题不仔细

 

HDU 1253 http://acm.hdu.edu.cn/showproblem.php?pid=1253

三维BFS,木有问题,注意优化下

 

HDU 1240 http://acm.hdu.edu.cn/showproblem.php?pid=1240

三维BFS水之


HDU 1429 http://acm.hdu.edu.cn/showproblem.php?pid=1429

BFS+二进制压缩存储,很明显要保存你拿过的钥匙的状态,总共10把钥匙,使用二进制压缩才1024个状态,开始还打算把门的状态也保存下来,结果莫名其秒的TLE,后来发现只需要钥匙的状态,因为钥匙可以用很多次,但是又莫名其妙的MLE,好吧,不解释,彻底晕了flag[x][y][key],表示在(x,y)手上钥匙状态为key


HDU 1254 http://acm.hdu.edu.cn/showproblem.php?pid=1254

经典的推箱子游戏,注意判重需要一个三维数组,可用两次B FS解决,或者BFS+DFS

详情请移步   http://blog.csdn.net/acm_cxlove/article/details/7639306


HDU 2612 http://acm.hdu.edu.cn/showproblem.php?pid=2612

两个人到同一点的和最短,分别以两个人为起点,遍历整个图,计算出到每个KFC的最短距离,然后枚举所有的KFC,算最小的代价


HDU 1983 http://acm.hdu.edu.cn/showproblem.php?pid=1983

最差的情况直接把出口或者入口四个方向封住,所以最多只要堵4次。BFS找出最短的路径,并保存路径,DFS处理路径上的点,BFS判断是否连通。


HDU 1195 http://acm.hdu.edu.cn/showproblem.php?pid=1195

题目不难,1W个可能,判重很简单,就是转化有点纠结,至少我写得很矬


HDU 2128 http://acm.hdu.edu.cn/showproblem.php?pid=2128

坑爹的题目,不过题目很好,BFS和DFS都可以做

具体请见http://blog.csdn.net/acm_cxlove/article/details/7635497

贴代码:

HDU 1240 三维BFS

/* 
02. ID:cxlove 
03. */  
04. #include<iostream>  
05. #include<cstdio>  
06. #include<cstring>  
07. #include<queue>  
08. #define LL unsigned long long  
09. using namespace std;  
10. int n,m,q;  
11. int way[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};  
12. char str[15][15][15];  
13. bool flag[15][15][15];  
14. struct Node{  
15.     int x,y,z,step;  
16.     bool check(){  
17.         if(x>=0&&y>=0&&z>=0&&x<n&&y<n&&z<n)  
18.             return true;  
19.         return false;  
20.     }  
21. }s,e,u,v;  
22. int bfs(){  
23.     if(s.x==e.x&&s.y==e.y&&s.z==e.z)  
24.         return 0;  
25.     queue<Node>que;  
26.     memset(flag,false,sizeof(flag));  
27.     s.step=0;  
28.     que.push(s);  
29.     flag[s.x][s.y][s.z]=true;  
30.     while(!que.empty()){  
31.         u=que.front();  
32.         que.pop();  
33.         for(int i=0;i<6;i++){  
34.             v=u;  
35.             v.x+=way[i][0];  
36.             v.y+=way[i][1];  
37.             v.z+=way[i][2];  
38.             v.step++;  
39.             if(v.check()&&flag[v.x][v.y][v.z]==false){               
40.                 flag[v.x][v.y][v.z]=true;  
41.                 if(v.x==e.x&&v.y==e.y&&v.z==e.z)  
42.                     return v.step;  
43.                 if(str[v.x][v.y][v.z]=='X')  
44.                     continue;  
45.                 que.push(v);  
46.             }  
47.         }  
48.     }  
49.     return -1;  
50. }  
51. char ch[100];  
52. int main(){  
53.     while(scanf("%s%d",ch,&n)!=EOF){  
54.         for(int i=0;i<n;i++)  
55.             for(int j=0;j<n;j++)  
56.                     scanf("%s",str[i][j]);  
57.         while(scanf("%s",ch)){  
58.             if(strcmp(ch,"END")==0)  
59.                 break;  
60.             sscanf(ch,"%d",&s.x);  
61.             scanf("%d%d%d%d%d",&s.y,&s.z,&e.x,&e.y,&e.z);  
62.             int ans=bfs();  
63.             if(ans==-1)  
64.                 printf("NO ROUTE\n");  
65.             else  
66.                 printf("%d %d\n",n,ans);  
67.         }  
68.   
69.     }  
70.     return 0;  
71. } 

HDU 1728 限制拐弯次数

#include<iostream>  
02. #include<cstdio>  
03. #include<cstring>  
04. #include<queue>  
05. #define LL unsigned long long  
06. using namespace std;  
07. int n,m,k;  
08. int way[4][2]={{1,0},{-1,0},{0,1},{0,-1}};  
09. char str[105][105];  
10. bool flag[105][105];  
11. struct Node{  
12.     int x,y,dir,cnt;  
13.     bool check(){  
14.         if(x>=0&&x<n&&y>=0&&y<m)  
15.             return true;  
16.         return false;  
17.     }  
18. }s,e,u,v;  
19. int bfs(){  
20.     queue<Node>que;  
21.     que.push(s);  
22.     memset(flag,false,sizeof(flag));  
23.     flag[s.x][s.y]=true;  
24.     while(!que.empty()){  
25.         u=que.front();  
26.         que.pop();  
27.         for(int i=0;i<4;i++){  
28.             v.cnt=u.cnt;  
29.             if(u.dir!=-1&&u.dir!=i)  
30.                 v.cnt++;  
31.             if(v.cnt>k)  
32.                 continue;      
33.             v.dir=i;  
34.             for(int j=1;;j++){  
35.                 v.x=u.x+way[i][0]*j;  
36.                 v.y=u.y+way[i][1]*j;  
37.                 if(v.check()&&str[v.x][v.y]!='*'){  
38.                     if(flag[v.x][v.y])  
39.                         continue;  
40.                     flag[v.x][v.y]=true;  
41.                     if(v.x==e.x&&v.y==e.y)  
42.                         return true;  
43.                     que.push(v);  
44.                 }  
45.                 else  
46.                     break;  
47.             }  
48.         }  
49.     }  
50.     return false;  
51. }  
52. int main(){  
53.     int t;  
54.     scanf("%d",&t);  
55.     while(t--){  
56.         scanf("%d%d",&n,&m);  
57.         for(int i=0;i<n;i++)  
58.             scanf("%s",str[i]);  
59.         scanf("%d%d%d%d%d",&k,&s.y,&s.x,&e.y,&e.x);  
60.         s.x--;s.y--;e.x--;e.y--;  
61.         s.cnt=0;s.dir=-1;  
62.         if((s.x==e.x&&s.y==e.y)||bfs())  
63.             printf("yes\n");  
64.         else  
65.             printf("no\n");  
66.     }  
67.     return 0;  
68. }  

HDU 1242 BFS+优先队列

#include<cstdio>  
02. #include<cstring>  
03. #include<iostream>  
04. #include<algorithm>  
05. #include<queue>  
06. #define LL long long  
07. using namespace std;  
08. struct Node{  
09.     int x,y,step;  
10.     bool operator<(const Node &n1)const{  
11.         return step>n1.step;  
12.     }  
13. }s,e,u,v;  
14. int n,m;  
15. char str[205][205];  
16. int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};  
17. int bfs(){  
18.     priority_queue<Node>que;  
19.     bool flag[205][205];  
20.     memset(flag,0,sizeof(flag));  
21.     s.step=0;  
22.     que.push(s);  
23.     flag[s.x][s.y]=1;  
24.     while(!que.empty()){  
25.         u=que.top();  
26.         que.pop();  
27.         for(int i=0;i<4;i++){  
28.             v.x=u.x+way[i][0];  
29.             v.y=u.y+way[i][1];  
30.             if(v.x>=0&&v.y>=0&&v.x<n&&v.y<m&&flag[v.x][v.y]==0&&str[v.x][v.y]!='#'){  
31.                 flag[v.x][v.y]=1;  
32.                 if(str[v.x][v.y]=='x')  
33.                     v.step=u.step+2;  
34.                 else  
35.                     v.step=u.step+1;  
36.                 if(v.x==e.x&&v.y==e.y)  
37.                     return v.step;  
38.                 que.push(v);  
39.             }  
40.         }  
41.     }  
42.     return -1;  
43. }  
44. int main(){  
45.     while(scanf("%d%d",&n,&m)!=EOF){  
46.         for(int i=0;i<n;i++){  
47.             scanf("%s",str[i]);  
48.             for(int j=0;j<m;j++)  
49.                 if(str[i][j]=='a'){  
50.                     s.x=i;  
51.                     s.y=j;  
52.                 }  
53.                 else if(str[i][j]=='r'){  
54.                     e.x=i;  
55.                     e.y=j;  
56.                 }  
57.         }  
58.         int ans=bfs();  
59.         if(ans==-1)  
60.             printf("Poor ANGEL has to stay in the prison all his life.\n");  
61.         else  
62.             printf("%d\n",ans);  
63.     }  
64.     return 0;  
65. }  

HDU 1429 BFS+二进制压缩

#include<iostream>  
02. #include<cstdio>  
03. #include<cstring>  
04. #include<queue>  
05. #include<vector>  
06. #define LL unsigned long long  
07. using namespace std;  
08. int n,m,T;  
09. int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};  
10. char str[21][21];  
11. bool flag[21][21][1024];  
12. struct Node{  
13.     short x,y,step;  
14.     short key;  
15.     bool check(){  
16.         if(x>=0&&x<n&&y>=0&&y<m)  
17.             return true;  
18.         return false;  
19.     }  
20. }s,e,u,v;  
21. queue<Node>que;  
22. int bfs(){  
23.     if(!que.empty())  
24.         que.pop();  
25.     que.push(s);  
26.     memset(flag,false,sizeof(flag));  
27.     while(!que.empty()){  
28.         u=que.front();  
29.         que.pop();  
30.          
31.         for(int i=0;i<4;i++){  
32.             v=u;  
33.             v.step++;  
34.             v.x+=way[i][0];  
35.             v.y+=way[i][1];   
36.               
37.             if(v.step>=T)  
38.                 break;  
39.             if(v.check()&&str[v.x][v.y]!='*'){  
40.                 if(str[v.x][v.y]=='^')  
41.                     return v.step;  
42.                 if(str[v.x][v.y]>='A'&&str[v.x][v.y]<='J'){  
43.                     if(((1<<(str[v.x][v.y]-'A'))&v.key)&&flag[v.x][v.y][v.key]==false){  
44.                         que.push(v);  
45.                         flag[v.x][v.y][v.key]=true;  
46.                     }  
47.                 }  
48.                 else if(str[v.x][v.y]>='a'&&str[v.x][v.y]<='j'){  
49.                     v.key|=(1<<(str[v.x][v.y]-'a'));  
50.                     if(flag[v.x][v.y][v.key]==false){             
51.                         que.push(v);  
52.                         flag[v.x][v.y][v.key]=true;  
53.                     }  
54.                 }  
55.                 else{  //相当于空地  
56.                     if(!flag[v.x][v.y][v.key]){  
57.                         flag[v.x][v.y][v.key]=true;  
58.                         que.push(v);  
59.                     }  
60.                 }  
61.             }  
62.   
63.         }  
64.     }  
65.     return -1;  
66. }  
67. int main(){  
68.     while(scanf("%d%d%d",&n,&m,&T)!=EOF){  
69.         for(int i=0;i<n;i++){  
70.             scanf("%s",str[i]);  
71.             for(int j=0;j<m;j++){  
72.                 if(str[i][j]=='@'){  
73.                     s.x=i;  
74.                     s.y=j;  
75.                     s.step=0;  
76.                     s.key=0;  
77.                 }  
78.             }  
79.         }  
80.         printf("%d\n",bfs());  
81.     }  
82.     return 0;  
83. }
原文链接:http://blog.csdn.net/alalalalalqp/article/details/9155457

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值