POJ_3083_Children of the Candy Corn(BFS+DFS)
/*
http://poj.org/problem?id=3083
看完题目之后自己心中便已有思路,因为前面做过几道这类搜索的题目了,但是自己真写起来的时候却
不知所措,只好看了 会网上的代码然后再自己写出来。虽然是看别人的但是着实从里面学了不少东西,
我想以后在遇着这种题目已经会个八九成了。
题意:
这道题的意思就是让你找走出迷宫的路径。分为左优先和右优先还有最短路径,输出的也是这三种路径的步数。
思路:1:对于最短路径肯定想到的是用广搜,因为广搜是一层一层的搜,适合这种找最小路径的问题。光搜实现的时候使用的是队列
两个位置变量,一个在首部,一个在尾部。尾部是入队操作,首部是访问操作,直到找到最短路径。队列元素可以使结构体类型,最重要的是保存
树的深度,可以这样理解,因为他是一层一层的访问,如果访问的是同一层他的深度是不加一的。因此队列元素保存的是走到当前位置(或者是在这一层时树的深度)。
这也是广度搜索与深度搜索的区别。
2:对于左优先和右优先的步数,使用的是深度优先搜索,类似于二叉树的前序遍历。即如果一直满足条件就一直搜下去,直到不满足条件后退一步再一直搜下去。
在这道题中,需要注意的是它访问过的点还有可能返回再访问,因此不能使用标记。处理方法就是使用一个方向变量d,d记录的是当前朝哪个方向走,
当三个方向都不满足时,那么只能往回走,此时前方便是往回走的方向,因此保证了他不会第二次回头。
3:还是那句话,对于每个函数,一定要想清楚这个函数的功能是什么。像这里的DFS他就是找左优先的步数,传过去的是起始点意思是说找从这个点
到结束点的步数,函数里面又出现了递归调用(到下一个位置的步数加一即为当前)。
*/
1 # include <stdio.h> 2 # include <string.h> 3 struct node 4 { 5 int r; 6 int c; 7 int depth; 8 }; 9 struct node q,p; 10 int map[50][50]; 11 int visit[50][50]; 12 int leftstep; 13 int rightstep; 14 int shortstep; 15 void DFS_left(int i,int j,int d) 16 { 17 leftstep++; 18 if(i==q.r && j==q.c ) 19 return ; 20 switch (d) 21 { 22 case 0: 23 { 24 if(map[i][j-1]) 25 DFS_left(i,j-1,1); 26 else if(map[i-1][j]) 27 DFS_left(i-1,j,0); 28 else if(map[i][j+1]) 29 DFS_left(i,j+1,3); 30 else 31 DFS_left(i+1,j,2); 32 break; 33 } 34 case 1: 35 { 36 if(map[i+1][j]) 37 DFS_left(i+1,j,2); 38 else if(map[i][j-1]) 39 DFS_left(i,j-1,1); 40 else if(map[i-1][j]) 41 DFS_left(i-1,j,0); 42 else 43 DFS_left(i,j+1,3); 44 break; 45 } 46 case 2: 47 { 48 if(map[i][j+1]) 49 DFS_left(i,j+1,3); 50 else if(map[i+1][j]) 51 DFS_left(i+1,j,2); 52 else if(map[i][j-1]) 53 DFS_left(i,j-1,1); 54 else 55 DFS_left(i-1,j,0); 56 break; 57 } 58 case 3: 59 { 60 if(map[i-1][j]) 61 DFS_left(i-1,j,0); 62 else if(map[i][j+1]) 63 DFS_left(i,j+1,3); 64 else if(map[i+1][j]) 65 DFS_left(i+1,j,2); 66 else 67 DFS_left(i,j-1,1); 68 break; 69 } 70 71 } 72 return ; 73 } 74 void DFS_right(int i,int j,int d) 75 { 76 rightstep++; 77 if(i==q.r && j==q.c ) 78 return ; 79 switch (d) 80 { 81 case 0: 82 { 83 if(map[i][j+1]) 84 DFS_right(i,j+1,3); 85 else if(map[i-1][j]) 86 DFS_right(i-1,j,0); 87 else if(map[i][j-1]) 88 DFS_right(i,j-1,1); 89 else 90 DFS_right(i+1,j,2); 91 break; 92 } 93 case 1: 94 { 95 if(map[i-1][j]) 96 DFS_right(i-1,j,0); 97 else if(map[i][j-1]) 98 DFS_right(i,j-1,1); 99 else if(map[i+1][j]) 100 DFS_right(i+1,j,2); 101 else 102 DFS_right(i,j+1,3); 103 break; 104 } 105 case 2: 106 { 107 if(map[i][j-1]) 108 DFS_right(i,j-1,1); 109 else if(map[i+1][j]) 110 DFS_right(i+1,j,2); 111 else if(map[i][j+1]) 112 DFS_right(i,j+1,3); 113 else 114 DFS_right(i-1,j,0); 115 break; 116 } 117 case 3: 118 { 119 if(map[i+1][j]) 120 DFS_right(i+1,j,2); 121 else if(map[i][j+1]) 122 DFS_right(i,j+1,3); 123 else if(map[i-1][j]) 124 DFS_right(i-1,j,0); 125 else 126 DFS_right(i,j-1,1); 127 break; 128 } 129 130 } 131 return ; 132 } 133 void BFS_short(int i,int j) 134 { 135 struct node x,dq[2000]; //dq为队列,临时记录待广搜的点。 136 int head=0,tail=0; //Initial; 137 dq[head].r=i; 138 dq[head].c=j; 139 dq[tail++].depth=1; 140 visit[i][j]=true; // 141 while(head<tail) 142 { 143 x=dq[head++]; 144 if(x.r==q.r && x.c==q.c) //找到终点结束 145 { 146 printf("%d\n",x.depth); 147 return ; 148 } 149 if(map[x.r][x.c-1] && !visit[x.r][x.c-1]) //广搜顺序可调换;如果他们都满足情况都得入队列。 150 { 151 visit[x.r][x.c-1]=1; 152 dq[tail].r=x.r; 153 dq[tail].c=x.c-1; 154 dq[tail++].depth=x.depth+1; //广搜深度加1;注意并不是队列加一个元素深度就加1; 155 //如果在同一层的元素深度不加1;x代表的是上一层。 156 } 157 if(map[x.r-1][x.c] && !visit[x.r-1][x.c]) 158 { 159 visit[x.r-1][x.c]=1; 160 dq[tail].r=x.r-1; 161 dq[tail].c=x.c; 162 dq[tail++].depth=x.depth+1; 163 } 164 if(map[x.r][x.c+1] && !visit[x.r][x.c+1]) 165 { 166 visit[x.r][x.c+1]=1; 167 dq[tail].r=x.r; 168 dq[tail].c=x.c+1; 169 dq[tail++].depth=x.depth+1; 170 } 171 if(map[x.r+1][x.c] && !visit[x.r+1][x.c]) 172 { 173 visit[x.r+1][x.c]=true; 174 dq[tail].r=x.r+1; 175 dq[tail].c=x.c; 176 dq[tail++].depth=x.depth+1; 177 } 178 179 } 180 return ; 181 182 } 183 int main() 184 { 185 int test,i,j,k,m,n,d; 186 char ch[50][50]; 187 scanf("%d",&test); 188 while(test--) 189 { 190 scanf("%d%d",&m,&n); 191 getchar(); 192 for(i=0;i<n;i++) 193 scanf("%s",ch[i]); 194 memset(map,0,sizeof(map)); //地图 195 memset(visit,0,sizeof(visit));//visit初始化都没被访问过 196 for(i=0;i<n;i++) 197 { 198 for(j=0;j<m;j++) 199 { 200 if(ch[i][j] == '.') 201 map[i+1][j+1]=1; 202 else if(ch[i][j]=='S') 203 { 204 map[i+1][j+1]=1; 205 visit[i+1][j+1]=1; 206 p.r=i+1; //记录起点 207 p.c=j+1; 208 if(i+1==n) //记录第一步走的方向。 209 d=0; //朝上 210 else if(i+1==1) 211 d=2; //朝下 212 else if(j+1==m) 213 d=1; //朝左 214 else if(j+1==1) 215 d=3; //朝右 216 } 217 else if(ch[i][j]=='E') 218 { 219 map[i+1][j+1]=1; 220 q.r=i+1; //记录终点; 221 q.c=j+1; 222 } 223 } 224 } 225 226 //left_step; 227 leftstep=1; 228 switch(d) 229 { 230 case 0: {DFS_left(p.r-1,p.c,0);break;}//0朝上,上走一步行减1; 231 case 1: {DFS_left(p.r,p.c-1,1);break;}//1朝左,左走一步列减1; 232 case 2: {DFS_left(p.r+1,p.c,2);break;}//2朝上 233 case 3: {DFS_left(p.r,p.c+1,3);break;}//3朝右 234 } 235 printf("%d ",leftstep); 236 237 //right_step; 238 rightstep=1; 239 switch(d) 240 { 241 case 0: {DFS_right(p.r-1,p.c,0);break;} 242 case 1: {DFS_right(p.r,p.c-1,1);break;} 243 case 2: {DFS_right(p.r+1,p.c,2);break;} 244 case 3: {DFS_right(p.r,p.c+1,3);break;} 245 } 246 printf("%d ",rightstep); 247 248 //shorted_step; 249 shortstep=0; 250 BFS_short(p.r,p.c); //起点为p开始广搜; 251 } 252 return 0; 253 }