BFS && DFS
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 }
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\n",ans); 48 } 49 return 0; 50 }
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\n"); 48 else printf("%d\n", ans); 49 } 50 return 0; 51 }
拿双向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\n", bfs()); 92 } 93 return 0; 94 }
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!\n"); 94 else printf("%d\n", ans); 95 } 96 return 0; 97 }
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.\n"); 95 else 96 printf("%d\n",min); 97 } 98 return 0; 99 }
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 }
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\n", bfs()); 85 } 86 return 0; 87 }
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\n",T,min_c,min_d); 94 } 95 }
POJ 1077 Eight
http://poj.org/problem?id=1077
经典八数码...据说不做此题,人生是不完整的...
判重就是一大难点:这题要用到全排列的变进制hash存储
然后算法的话 bfs可能险超时 双向bfs和A*是比较好的选择... 至于代码吗,还没写 哈哈...
持续更新中...