BFS && DFS
分类:
IT文章
•
2023-11-29 20:38:13
HDOJ 1312 Red and Black
http://acm.hdu.edu.cn/showproblem.php?pid=1312
很裸的dfs,在dfs里面写上ans++,能到几个点就调了几次dfs,最后ans就是答案
1 #include<cstdio>
2 #include<iostream>
3 using namespace std;
4 char map[22][22];
5 int n,m,si,sj,ans;
6 int dir[4][2] = {{1,0}, {-1,0}, {0,-1}, {0,1}};
7 int dfs(int x, int y)
8 {
9 if (x<=0||x>m||y<=0||y>n)
10 {
11 return 0;
12 }
13 ans++;
14 for (int i = 0; i < 4; ++i)
15 {
16 if (map[x+dir[i][0]][y+dir[i][1]] == '.')
17 {
18 map[x+dir[i][0]][y+dir[i][1]] = 'X';//把访问过的置为“墙”,以免重复计算
19 dfs(x+dir[i][0],y+dir[i][1]);
20 }
21 }
22
23 }
24 int main()
25 {
26 while(scanf("%d%d", &n, &m) != EOF)
27 {
28 if (n == 0 && m == 0)
29 {
30 break;
31 }
32 for (int i = 1; i <= m; ++i)
33 {
34 for (int j = 1; j <= n; ++j)
35 {
36 cin >> map[i][j];
37 if (map[i][j] == '@')
38 {
39 si = i;
40 sj = j;
41 }
42 }
43 }
44 ans = 0;
45 dfs(si,sj);
46 cout << ans << endl;
47 }
48 return 0;
49 }
View Code
HDOJ 1241 Oil Deposits
http://acm.hdu.edu.cn/showproblem.php?pid=1241
简单dfs 求连通块 对地图中的每个@点,ans++调dfs 把和它连通的都标记了
调dfs的次数,就是连通油田的块数
1 #include<stdio.h>
2 int m,n;
3 char map[105][105];
4 int dir[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
5 void dfs(int x,int y)
6 {
7 map[x][y]='*';
8 for(int i=0;i<8;i++)
9 {
10 int fx=x+dir[i][0];
11 int fy=y+dir[i][1];
12 if(fx>=0&&fy>=0&&fx<m&&fy<n)
13 {
14 if(map[fx][fy]=='@')
15 {
16 dfs(fx,fy);
17 }
18 }
19 }
20 }
21 int main()
22 {
23 while(~scanf("%d%d",&m,&n))
24 {
25 int ans=0;
26 if(m==0) break;
27 getchar();
28 for(int i=0;i<m;i++)
29 {
30 for(int j=0;j<n;j++)
31 {
32 scanf("%c",&map[i][j]);
33 }
34 getchar();
35 }
36 for(int i=0;i<m;i++)
37 {
38 for(int j=0;j<n;j++)
39 {
40 if(map[i][j]=='@')
41 {
42 ans++;
43 dfs(i,j);
44 }
45 }
46 }
47 printf("%d
",ans);
48 }
49 return 0;
50 }
View Code
COJ 1224 ACM小组的古怪象棋
http://122.207.68.93/OnlineJudge/problem.php?id=1224
马吃将最少要几步...而且这个将还是不会动的...
1 #include<cstdio>
2 #include<cstring>
3 #include<queue>
4 using namespace std;
5 int n,m,x,y,si,sj,ans;
6 int map[25][25];//这里map实际上起到的是vis的作用
7 int dir[][2]={1,2,2,1,2,-1,1,-2,-1,-2,-2,-1,-2,1,-1,2};
8 struct node
9 {
10 int x,y,d;
11 };
12 int bfs()
13 {
14 queue<node> q;
15 while(!q.empty()) q.pop();
16 node now,next;
17 now.x=si;
18 now.y=sj;
19 now.d=0;
20 q.push(now);
21 map[now.x][now.y]=1;
22 while(!q.empty())
23 {
24 now = q.front();
25 if(now.x==x&&now.y==y) return now.d;
26 q.pop();
27 for (int i = 0; i < 8; ++i)
28 {
29 next.x=now.x+dir[i][0];
30 next.y=now.y+dir[i][1];
31 if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&map[next.x][next.y]==0)
32 {
33 next.d=now.d+1;
34 q.push(next);
35 map[next.x][next.y]=1;
36 }
37 }
38 }
39 return -1;
40 }
41 int main()
42 {
43 while(scanf("%d%d%d%d%d%d",&n,&m,&x,&y,&si,&sj)!=EOF)
44 {
45 memset(map,0,sizeof(map));
46 ans = bfs();
47 if(ans==-1) printf("-1
");
48 else printf("%d
", ans);
49 }
50 return 0;
51 }
View Code
拿双向BFS也写了一个 AC了 不过我总感觉怪怪的...
1 #include<cstdio>
2 #include<queue>
3 #include<cstring>
4 using namespace std;
5 int n,m,si,sj,ei,ej;
6 int dir[][2]={1,2,2,1,2,-1,1,-2,-1,-2,-2,-1,-2,1,-1,2};
7 int vis[25][25],mi[25][25];//vis 0表示尚未访问过 1表示被正向bfs扫到过 2表示被反向bfs扫到
8 struct node //mi保存到达这个点的最小步数 以便两个bfs相遇时读出步数
9 { //具体就是一层一层地扫了 遇到了(1遇见2 或者 2遇见1)就立即返回
10 int x,y,d;
11 };
12 bool check(int x,int y)
13 {
14 if(x>0&&x<=n&&y>0&&y<=m) return true;
15 return false;
16 }
17 int bfs()
18 {
19 queue<node> q1,q2;
20 while(!q1.empty()) q1.pop();
21 while(!q2.empty()) q2.pop();
22 node now,next;
23 now.x=si;
24 now.y=sj;
25 now.d=0;
26 q1.push(now);
27 mi[si][sj]=0;
28 now.x=ei;
29 now.y=ej;
30 now.d=0;
31 q2.push(now);
32 mi[ei][ej]=0;
33 while(!q1.empty()||!q2.empty())
34 {
35 if(!q1.empty())
36 {
37 now=q1.front();
38 q1.pop();
39 if(vis[now.x][now.y]==1) continue;
40 if(vis[now.x][now.y]==2) return now.d+mi[now.x][now.y];
41 vis[now.x][now.y]=1;
42 for(int i=0;i<8;i++)
43 {
44 next.x=now.x+dir[i][0];
45 next.y=now.y+dir[i][1];
46 if(check(next.x,next.y)&&vis[next.x][next.y]!=1)
47 {
48 if(vis[next.x][next.y]==2) return now.d+mi[next.x][next.y]+1;
49 else
50 {
51 next.d=now.d+1;
52 mi[next.x][next.y]=next.d;
53 q1.push(next);
54 }
55 }
56 }
57 }
58 //
59 if(!q2.empty())
60 {
61 now=q2.front();
62 q2.pop();
63 if(vis[now.x][now.y]==2) continue;
64 if(vis[now.x][now.y]==1) return now.d+mi[now.x][now.y];
65 vis[now.x][now.y]=2;
66 for(int i=0;i<8;i++)
67 {
68 next.x=now.x+dir[i][0];
69 next.y=now.y+dir[i][1];
70 if(check(next.x,next.y)&&vis[next.x][next.y]!=2)
71 {
72 if(vis[next.x][next.y]==1) return now.d+mi[next.x][next.y]+1;
73 else
74 {
75 next.d=now.d+1;
76 mi[next.x][next.y]=next.d;
77 q2.push(next);
78 }
79 }
80 }
81 }
82 }
83 return -1;
84 }
85 int main()
86 {
87 while(scanf("%d%d%d%d%d%d",&n,&m,&si,&sj,&ei,&ej)!=EOF)
88 {
89 memset(vis,0,sizeof(vis));
90 memset(mi,-1,sizeof(mi));
91 printf("%d
", bfs());
92 }
93 return 0;
94 }
View Code
COJ 1259 跳跳
http://122.207.68.93/OnlineJudge/problem.php?id=1259
为数字2到9的都建一个队列,读地图时候遇到了就加到各自的队列里
在bfs主体中,如果探索到了2到9的数字,就把相应队列里的结点顺便一并添加到bfs的主队列中...
1 #include<cstdio>
2 #include<queue>
3 #include<cstring>
4 #define REP(i,a,b) for(int i = a; i < b; i++)
5 using namespace std;
6 char map[105][105];
7 int vis[105][105];
8 int dir[][2]={1,0,-1,0,0,1,0,-1};
9 int n,si,sj,ei,ej,ans;
10 queue<int> q[8];
11 struct node
12 {
13 int x,y,d;
14 }now,next;
15 int bfs()
16 {
17 queue<node> qq;
18 while(!qq.empty()) qq.pop();
19 now.x=si;
20 now.y=sj;
21 now.d=0;
22 qq.push(now);
23 while(!qq.empty())
24 {
25 now=qq.front();
26 qq.pop();
27 if(now.x==ei&&now.y==ej) return now.d;
28 if(vis[now.x][now.y]) continue;
29 vis[now.x][now.y]=1;
30 REP(i,0,4) {
31 next.x=now.x+dir[i][0];
32 next.y=now.y+dir[i][1];
33 if(next.x>=0&&next.x<n&&next.y>=0&&next.y<n&&map[next.x][next.y]!='1'&&vis[next.x][next.y]==0)
34 {
35 if(map[next.x][next.y]=='0')
36 {
37 next.d=now.d+1;
38 qq.push(next);
39 }else
40 {
41 int a=map[next.x][next.y]-'0';
42 if(a>=2&&a<=9)
43 {
44 next.d=now.d+1;
45 qq.push(next);
46 while(!q[a-2].empty())
47 {
48 next.x=q[a-2].front();
49 q[a-2].pop();
50 next.y=q[a-2].front();
51 q[a-2].pop();
52 next.d=now.d+1;
53 qq.push(next);
54 }
55 }
56 }
57 }
58 }
59 }
60 return -1;
61 }
62 int main()
63 {
64 while(scanf("%d",&n)!=EOF)
65 {
66 REP(i,0,8) {
67 while(!q[i].empty()) q[i].pop();
68 }
69 getchar();
70 memset(vis,0,sizeof(vis));
71 REP(i,0,n) {
72 REP(j,0,n) {
73 scanf("%c",&map[i][j]);
74 if(map[i][j]=='S')
75 {
76 si=i;
77 sj=j;
78 }else if(map[i][j]=='E')
79 {
80 ei=i;
81 ej=j;
82 }else if((map[i][j]-'0')>=2&&(map[i][j]-'0')<=9)
83 {
84 q[(map[i][j]-'0')-2].push(i);
85 q[(map[i][j]-'0')-2].push(j);
86 }
87 }
88 getchar();
89 }
90 map[si][sj]='1';
91 map[ei][ej]='0';
92 ans=bfs();
93 if(ans==-1) printf("Oh No!
");
94 else printf("%d
", ans);
95 }
96 return 0;
97 }
View Code
HDOJ 1242 Rescue
http://acm.hdu.edu.cn/showproblem.php?pid=1242
bfs+优先队列
实际上救援可以有多个,而公主只有一个,所以这题应该从公主开始bfs,遇到救援就停止,但是杭电这道题貌似只有一个救援...
1 #include <stdio.h>
2 #include <string.h>
3 #include <vector>
4 #include <queue>
5 using namespace std;
6 char map[201][201];
7 bool flag[201][201];
8 int dx[]={1,0,-1,0};
9 int dy[]={0,1,0,-1};
10 int n,m;
11 struct node
12 {
13 int x;
14 int y;
15 int time;
16 friend bool operator<(node a,node b) //优先队列
17 {
18 return a.time>b.time; //时间小的先出队
19 }
20 };
21 int BFS(int x,int y)
22 {
23 priority_queue<node> q;
24 node now,next;
25 int i;
26 now.x=x;
27 now.y=y;
28 now.time=0;
29 q.push(now);
30 flag[now.y][now.x]=true;
31
32 while(!q.empty())
33 {
34 now=q.top();
35 for(i=0;i<4;i++)
36 {
37 next.x=now.x+dx[i];
38 next.y=now.y+dy[i];
39 if(next.x>=1&&next.x<=m&&next.y>=1&&next.y<=n&&map[next.y][next.x]!='#'&&flag[next.y][next.x]==false)
40 {
41 flag[next.y][next.x]=true;
42 next.time=now.time+1;
43 if(map[next.y][next.x]=='x')
44 next.time++;
45
46 q.push(next); //next更新后在入队
47 if(map[next.y][next.x]=='a')
48 return next.time;
49 }
50 }
51 q.pop();
52 }
53 return -1;
54 }
55 int main()
56 {
57 int i,j,xe,ye;
58 while(scanf("%d%d",&n,&m)!=EOF)
59 {
60 vector<node> r;
61 r.clear();
62 for(i=1;i<=n;i++)
63 {
64 getchar();
65 for(j=1;j<=m;j++)
66 {
67 scanf("%c",&map[i][j]);
68 }
69 }
70 for(i=1;i<=n;i++)
71 {
72 for(j=1;j<=m;j++)
73 {
74 if(map[i][j]=='r')
75 {
76 node temp;
77 temp.y=i;
78 temp.x=j;
79 temp.time=0;
80 r.push_back(temp);
81 }
82 }
83 }
84
85 int min=99999;
86 for(i=0;i<r.size();i++)
87 {
88 memset(flag,false,sizeof(flag));
89 int tem=BFS(r[i].x,r[i].y);
90 if(tem<min)
91 min=tem;
92 }
93 if(min<0||r.size()==0) //要判断是否有r,之前没判断,WA了几次
94 printf("Poor ANGEL has to stay in the prison all his life.
");
95 else
96 printf("%d
",min);
97 }
98 return 0;
99 }
View Code
HDOJ 1026 Ignatius and the Princess I
http://acm.hdu.edu.cn/showproblem.php?pid=1026
bfs+记录路径 多开一个path[][]用于记录路径 并在结构体里增加一对pre指向前一个节点的x,y坐标
然后从终点开始把各个节点入栈,出栈的时候就是从起点到终点了...
1 #include <iostream>
2 #include <queue>
3 #include <stack>
4 using namespace std;
5 typedef struct Node{
6 int x, y, cost;
7 int prex, prey;
8 }Node;
9 int N, M;
10 char maze[105][105]; // 记录初始输入
11 Node path[105][105]; // 记录路径
12 int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
13 // 判断(x, y)是否可行
14 bool isOK(int x, int y)
15 {
16 if(x>=0 && x<N && y>=0 && y<M && maze[x][y]!='X')
17 return 1;
18 else
19 return 0;
20 }
21 void Init()
22 {
23 int i, j;
24 for(i = 0; i < N; ++i)
25 for(j = 0; j < M; ++j)
26 path[i][j].cost = -1;
27 }
28 void backPath(int x, int y)
29 {
30 stack<Node> S;
31 Node a, b;
32 int cc = 1, tmp;
33
34 cout << "It takes " << path[N - 1][M - 1].cost
35 << " seconds to reach the target position, let me show you the way." << endl;
36 a = path[N - 1][M - 1];
37 while(1)
38 {
39 if(a.x == 0 && a.y == 0)
40 break;
41 S.push(a);
42 a = path[a.prex][a.prey];
43 }
44
45 a = path[0][0];
46
47 while(!S.empty())
48 {
49 b = S.top();
50 S.pop();
51 if(maze[b.x][b.y] == '.')
52 cout << cc++ << "s:(" << a.x << "," << a.y << ")->(" << b.x << "," << b.y << ")" << endl;
53 else
54 {
55 cout << cc++ << "s:(" << a.x << "," << a.y << ")->(" << b.x << "," << b.y << ")" << endl;
56 tmp = maze[b.x][b.y] - '0';
57 while(tmp--)
58 cout << cc++ << "s:FIGHT AT (" << b.x << "," << b.y << ")" <<endl;
59 }
60 a = b;
61 }
62 cout<<"FINISH"<<endl;
63 }
64 int BFS(int x, int y)
65 {
66 queue<Node> Q;
67 Node a, b;
68 a.x = a.y = a.cost = a.prex = a.prey = 0;
69 if(maze[0][0] != '.')
70 a.cost = maze[0][0] - '0';
71 path[0][0] = a;
72 Q.push(a);
73 while(!Q.empty())
74 {
75 a = Q.front();
76 Q.pop();
77 for(int i=0; i<4; ++i)
78 {
79 b.x = a.x + dir[i][0];
80 b.y = a.y + dir[i][1];
81 if(!isOK(b.x, b.y))
82 continue;
83 if(maze[b.x][b.y] == '.')
84 b.cost = a.cost + 1;
85 else
86 b.cost = a.cost + maze[b.x][b.y]-'0' + 1;
87 if(b.cost < path[b.x][b.y].cost || path[b.x][b.y].cost == -1)
88 {
89 b.prex = a.x;
90 b.prey = a.y;
91 path[b.x][b.y] = b;
92 Q.push(b);
93 }
94 }
95 }
96 if(path[N - 1][M - 1].cost == -1)
97 {
98 cout << "God please help our poor hero." << endl;
99 cout << "FINISH" << endl;
100 return 0;
101 }
102 backPath(N-1, M-1);
103 }
104 int main()
105 {
106 while(cin >> N >> M)
107 {
108 memset(maze, 0, sizeof(maze));
109 for(int i=0; i<N; ++i)
110 for(int j=0; j<M; ++j)
111 cin >> maze[i][j];
112 Init();
113 BFS(0, 0);
114 }
115 return 0;
116 }
View Code
HDOJ 1195 Open the Lock
http://acm.hdu.edu.cn/showproblem.php?pid=1195
这题相当蛋疼,光是那四位数字在那转换就让我写的菊紧...
这题可以用双向bfs,不过这题数据比较弱,写了个bfs过了,也就没心情优化了...
1 #include<cstdio>
2 #include<queue>
3 #include<cstring>
4 #define REP(i,a,b) for(int i = a; i < b; i++)
5 using namespace std;
6 int T,b,start,end,tmp[4],cur[4],vis[10000];
7 int cal(int n)
8 {
9 tmp[0]=n/1000;
10 tmp[1]=(n%1000)/100;
11 tmp[2]=(n%100)/10;
12 tmp[3]=n%10;
13 return 0;
14 }
15 int init()
16 {
17 cur[0]=tmp[0];
18 cur[1]=tmp[1];
19 cur[2]=tmp[2];
20 cur[3]=tmp[3];
21 return 0;
22 }
23 int ans()
24 {
25 return cur[0]*1000+cur[1]*100+cur[2]*10+cur[3];
26 }
27 struct node
28 {
29 int v,d;
30 }now,next;
31 int bfs()
32 {
33 queue<node> q;
34 while(!q.empty()) q.pop();
35 now.v=start;
36 now.d=0;
37 q.push(now);
38 while(!q.empty())
39 {
40 now=q.front();
41 if(now.v==end) return now.d;
42 q.pop();
43 if(vis[now.v]) continue;
44 vis[now.v]=1;
45 cal(now.v);
46 REP(i,0,4) {
47 init();
48 cur[i]++;
49 if(cur[i]==10) cur[i]=1;
50 next.v=ans();
51 if(vis[next.v]) continue;
52 next.d=now.d+1;
53 q.push(next);
54 }
55 REP(i,0,4) {
56 init();
57 cur[i]--;
58 if(cur[i]==0) cur[i]=9;
59 next.v=ans();
60 if(vis[next.v]) continue;
61 next.d=now.d+1;
62 q.push(next);
63 }
64 next.v=tmp[1]*1000+tmp[0]*100+tmp[2]*10+tmp[3];
65 next.d=now.d+1;
66 if(!vis[next.v]) q.push(next);
67 next.v=tmp[0]*1000+tmp[2]*100+tmp[1]*10+tmp[3];
68 next.d=now.d+1;
69 if(!vis[next.v]) q.push(next);
70 next.v=tmp[0]*1000+tmp[1]*100+tmp[3]*10+tmp[2];
71 next.d=now.d+1;
72 if(!vis[next.v]) q.push(next);
73 }
74 return 0;
75 }
76 int main()
77 {
78 scanf("%d",&T);
79 while(T--)
80 {
81 memset(vis,0,sizeof(vis));
82 scanf("%d",&start);
83 scanf("%d",&end);
84 printf("%d
", bfs());
85 }
86 return 0;
87 }
View Code
COJ 1336 Interesting Calculator
http://122.207.68.93/OnlineJudge/problem.php?id=1336
这题是湖南第九届省赛的题,bfs+优先队列 写不好的话空间可能会爆
我是多用了一个mi数组存达到这个数需要的最小步骤,如果扩展中遇到这个点,但是此时的d已经比保存的大了,就不扩展此结点...
看是觉得*0和*1 +0这些纯属没用的状态 WA好几次才发现 *0还是有用的...当第二数比第一个小时,要先*0 具体看代码吧
1 #include<cstdio>
2 #include<queue>
3 #include<cstring>
4 #define MAXN 100005
5 #define REP(i,a,b) for(int i = a; i < b; i++)
6 using namespace std;
7 int start,end,T=0,min_c,min_d;
8 int a[10],b[10],c[10];
9 int mi[MAXN],vis[MAXN];
10 struct Node
11 {
12 int val,cost,dep;
13 friend bool operator<(Node a,Node b)
14 {
15 if(a.cost==b.cost) return a.dep>b.dep;
16 else return a.cost>b.cost;
17 }
18 }now,next;
19 int bfs()
20 {
21 priority_queue<Node> q;
22 while(!q.empty()) q.pop();
23 now.cost=0;
24 now.dep=0;
25 now.val=start;
26 mi[now.val]=0;
27 q.push(now);
28 while(!q.empty())
29 {
30 now=q.top();
31 q.pop();
32 if(vis[now.val]) continue;
33 vis[now.val]=1;
34 if(now.val==end)
35 {
36 min_c=now.cost;
37 min_d=now.dep;
38 return 1;
39 }
40 REP(i,0,10) {
41 next.val=now.val*10+i;
42 if(next.val<=end)
43 {
44 next.cost=now.cost+a[i];
45 next.dep=now.dep+1;
46 if(!vis[next.val]&&mi[next.val]>next.cost)
47 {
48 q.push(next);
49 mi[next.val]=next.cost;
50 }
51 }
52 }
53 REP(i,0,10) {
54 next.val=now.val+i;
55 if(next.val<=end)
56 {
57 next.cost=now.cost+b[i];
58 next.dep=now.dep+1;
59 if(!vis[next.val]&&mi[next.val]>next.cost)
60 {
61 q.push(next);
62 mi[next.val]=next.cost;
63 }
64 }
65 }
66 REP(i,0,10) {//开始这里i是从2开始的...WA好几发
67 next.val=now.val*i;
68 if(next.val<=end)
69 {
70 next.cost=now.cost+c[i];
71 next.dep=now.dep+1;
72 if(!vis[next.val]&&mi[next.val]>next.cost)
73 {
74 q.push(next);
75 mi[next.val]=next.cost;
76 }
77 }
78 }
79 }
80 return 0;
81 }
82 int main()
83 {
84 while(scanf("%d%d",&start,&end)!=EOF)
85 {
86 T++;
87 memset(mi,0x3f,sizeof(mi));
88 memset(vis,0,sizeof(vis));
89 REP(i,0,10) scanf("%d",&a[i]);
90 REP(i,0,10) scanf("%d",&b[i]);
91 REP(i,0,10) scanf("%d",&c[i]);
92 bfs();
93 printf("Case %d: %d %d
",T,min_c,min_d);
94 }
95 }
View Code
POJ 1077 Eight
http://poj.org/problem?id=1077
经典八数码...据说不做此题,人生是不完整的...
判重就是一大难点:这题要用到全排列的变进制hash存储
然后算法的话 bfs可能险超时 双向bfs和A*是比较好的选择... 至于代码吗,还没写 哈哈...
持续更新中...