poj3083 Children of the Candy Corn dfs 和 bfs 的综合,终于AC了
2014-03-13
TLE后就把输入和输出全改成 scanf( ) 和 printf( ) 了,但还是超时。感觉是搜索最短路径时用的方法太慢了。下面是TLE的代码:
1 ///2014.3.11 - 2014.3.13 2 ///poj3083 3 4 #include <iostream> 5 #include <cstdio> 6 using namespace std; 7 8 int w,h; ///记录迷宫的大小 9 char maze[50][50]; ///记录迷宫 10 int start_w,start_h; ///记录迷宫的开始位置 11 int start_pre; ///其前一步的相对于现在位置的方向, 12 ///0表示在右,1表示在上面,2表示在左边,3是下面 13 bool findmin; ///标记有没有找到最短路 14 int step; 15 16 int next_w[4] = {1,0,-1,0}; ///方便走下一步 17 int next_h[4] = {0,-1,0,1}; 18 19 void dfs(int h,int w,int pre,int l_r) 20 { 21 step++; 22 if( maze[h][w]=='E' ){ 23 return; 24 } 25 if( maze[h+next_h[(pre+l_r)%4] ][w+next_w[(pre+l_r)%4] ] !='#' ){ 26 dfs( h+next_h[(pre+l_r)%4], w+next_w[(pre+l_r)%4], (pre+l_r+2)%4,l_r); 27 } 28 else if( maze[h+next_h[(pre+l_r*2)%4] ][w+next_w[(pre+l_r*2)%4] ] !='#' ){ 29 dfs( h+next_h[(pre+l_r*2)%4], w+next_w[(pre+l_r*2)%4], (pre+l_r*2+2)%4,l_r); 30 } 31 else if( maze[h+next_h[(pre+l_r*3)%4] ][w+next_w[(pre+l_r*3)%4] ] !='#' ){ 32 dfs( h+next_h[(pre+l_r*3)%4], w+next_w[(pre+l_r*3)%4], (pre+l_r*3+2)%4,l_r); 33 } 34 else{ 35 dfs( h+next_h[pre], w+next_w[pre], (pre+2)%4,l_r); 36 } 37 } 38 39 void bfs(int h,int w,int pre,int deep) 40 { 41 step++; 42 43 if( findmin ) return; 44 if( maze[h][w]=='E' ){ 45 findmin = true; 46 return; 47 } 48 if( deep==step ){ 49 return; 50 } 51 52 if( maze[h+next_h[(pre+1)%4] ][w+next_w[(pre+1)%4] ] !='#' ){ 53 bfs( h+next_h[(pre+1)%4], w+next_w[(pre+1)%4], (pre+1+2)%4,deep); 54 step--; 55 } 56 if( maze[h+next_h[(pre+2)%4] ][w+next_w[(pre+2)%4] ] !='#' ){ 57 bfs( h+next_h[(pre+2)%4], w+next_w[(pre+2)%4], (pre+2+2)%4,deep); 58 step--; 59 } 60 if( maze[h+next_h[(pre+3)%4] ][w+next_w[(pre+3)%4] ] !='#' ){ 61 bfs( h+next_h[(pre+3)%4], w+next_w[(pre+3)%4], (pre+3+2)%4,deep); 62 step--; 63 } 64 } 65 66 void init() 67 { 68 char c; 69 scanf("%d%d",&w,&h); 70 scanf("%c",&c); 71 for(int i=1 ; i<=h ; i++){ 72 for(int j=1 ; j<=w ; j++){ 73 scanf("%c",&c); 74 maze[i][j] = c; 75 if( c=='S' ){ 76 start_w = j; 77 start_h = i; 78 if( j==1 ) 79 start_pre = 2; 80 else if( j==w ) 81 start_pre = 0; 82 else if( i==1 ) 83 start_pre = 1; 84 else 85 start_pre = 3; 86 } 87 } 88 scanf("%c",&c); 89 } 90 step = 0; 91 } 92 93 int main() 94 { 95 // freopen("in","r",stdin); 96 // freopen("out","w",stdout); 97 98 int cas; 99 scanf("%d",&cas); 100 while( cas-- ){ 101 init(); 102 103 dfs(start_h,start_w,start_pre,3); 104 printf("%d ",step); 105 106 step = 0; 107 dfs(start_h,start_w,start_pre,1); 108 printf("%d ",step); 109 110 findmin = false; 111 int deep; 112 for(deep=1 ; !findmin ; deep++){ 113 step = 0; 114 bfs(start_h,start_w,start_pre,deep); 115 } 116 printf("%d\n",--deep); 117 } 118 return 0; 119 }
2014-03-17
这个题折磨了我好几天,知道自己的bfs方法太慢,但是自己太菜了,不知道怎么改。各种不甘心,所以上英语课时找出CSDN上那个很厉害的“小优学姐”的代码研究。(http://blog.csdn.net/lyy289065406/article/details/6647668)
得到启发思路,从新写代码A掉这一题,废话少说,上代码:
1 ///2014.3.17 2 ///poj3083 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstring> 7 using namespace std; 8 9 int W,H; ///记录迷宫的大小 10 char maze[50][50]; ///记录迷宫 11 int start_w,start_h; ///记录迷宫的开始位置 12 int start_pre; ///其前一步的相对于现在位置的方向, 13 ///0表示在右,1表示在上面,2表示在左边,3是下面 14 int step; 15 16 int next_w[4] = {1,0,-1,0}; ///方便走下一步 17 int next_h[4] = {0,-1,0,1}; 18 19 void dfs(int h,int w,int pre,int l_r) ///l_r变量决定优先左拐还是右拐 20 { 21 step = 1; ///起点是第一步 22 while( maze[h][w] != 'E' ){ 23 step++; 24 if( maze[h+next_h[(pre+l_r)%4] ][w+next_w[(pre+l_r)%4] ] !='#' ){ 25 h = h+next_h[(pre+l_r)%4]; 26 w = w+next_w[(pre+l_r)%4]; 27 pre = (pre+l_r+2)%4; 28 } 29 else if( maze[h+next_h[(pre+l_r*2)%4] ][w+next_w[(pre+l_r*2)%4] ] !='#' ){ 30 h = h+next_h[(pre+l_r*2)%4]; 31 w = w+next_w[(pre+l_r*2)%4]; 32 pre = (pre+l_r*2+2)%4; 33 } 34 else if( maze[h+next_h[(pre+l_r*3)%4] ][w+next_w[(pre+l_r*3)%4] ] !='#' ){ 35 h = h+next_h[(pre+l_r*3)%4]; 36 w = w+next_w[(pre+l_r*3)%4]; 37 pre = (pre+l_r*3+2)%4; 38 } 39 else{ 40 h = h+next_h[pre]; 41 w = w+next_w[pre]; 42 pre = (pre+2)%4; 43 } 44 } 45 printf("%d ",step); 46 } 47 48 void bfs(int h,int w) ///建立一个搜索树,'E'的深度就是最少的步数 49 { 50 int p,q; 51 p=q=0; 52 53 int h_queue[1650]; ///记录搜到的每一步的h坐标 54 int w_queue[1650]; ///记录搜到的每一步的w坐标 55 int deep_queue[1650]; ///记录搜到的每一步的深度 56 57 bool visited[50][50]; 58 memset(visited,false,sizeof(bool)*50*50); 59 60 h_queue[1] = h; 61 w_queue[1] = w; 62 deep_queue[1] = 1; 63 p=0; 64 q=1; 65 66 while( p!=q ){ 67 p++; 68 if( maze[ h_queue[p] ][ w_queue[p]+1 ]=='.' 69 && !visited[ h_queue[p] ][ w_queue[p]+1 ] 70 || maze[ h_queue[p] ][ w_queue[p]+1 ]=='E'){ 71 if(maze[ h_queue[p] ][ w_queue[p]+1 ]=='E'){ 72 printf("%d\n",deep_queue[p]+1 ); 73 break; 74 } 75 q++; 76 visited[ h_queue[p] ][ w_queue[p]+1 ] = true; 77 h_queue[q] = h_queue[p]; 78 w_queue[q] = w_queue[p]+1; 79 deep_queue[q] = deep_queue[p]+1; 80 } 81 if( maze[ h_queue[p]+1 ][ w_queue[p] ]=='.' 82 && !visited[ h_queue[p]+1 ][ w_queue[p] ] 83 || maze[ h_queue[p]+1 ][ w_queue[p] ]=='E'){ 84 if(maze[ h_queue[p]+1 ][ w_queue[p] ]=='E'){ 85 printf("%d\n",deep_queue[p]+1 ); 86 break; 87 } 88 q++; 89 visited[ h_queue[p]+1 ][ w_queue[p] ] = true; 90 h_queue[q] = h_queue[p]+1; 91 w_queue[q] = w_queue[p]; 92 deep_queue[q] = deep_queue[p]+1; 93 } 94 if( maze[ h_queue[p] ][ w_queue[p]-1 ]=='.' 95 && !visited[ h_queue[p] ][ w_queue[p]-1 ] 96 || maze[ h_queue[p] ][ w_queue[p]-1 ]=='E'){ 97 if(maze[ h_queue[p] ][ w_queue[p]-1 ]=='E'){ 98 printf("%d\n",deep_queue[p]+1 ); 99 break; 100 } 101 q++; 102 visited[ h_queue[p] ][ w_queue[p]-1 ] = true; 103 h_queue[q] = h_queue[p]; 104 w_queue[q] = w_queue[p]-1; 105 deep_queue[q] = deep_queue[p]+1; 106 } 107 if( maze[ h_queue[p]-1 ][ w_queue[p] ]=='.' 108 && !visited[ h_queue[p]-1 ][ w_queue[p] ] 109 || maze[ h_queue[p]-1 ][ w_queue[p] ]=='E'){ 110 if(maze[ h_queue[p]-1 ][ w_queue[p] ]=='E'){ 111 printf("%d\n",deep_queue[p]+1 ); 112 break; 113 } 114 q++; 115 visited[ h_queue[p]-1 ][ w_queue[p] ] = true; 116 h_queue[q] = h_queue[p]-1; 117 w_queue[q] = w_queue[p]; 118 deep_queue[q] = deep_queue[p]+1; 119 } 120 } 121 } 122 123 void init() 124 { 125 char c; 126 scanf("%d%d",&W,&H); 127 scanf("%c",&c); 128 for(int i=1 ; i<=H ; i++){ ///读入迷宫 129 for(int j=1 ; j<=W ; j++){ 130 scanf("%c",&c); 131 maze[i][j] = c; 132 if( c=='S' ){ ///找到起点并设置起点信息 133 start_w = j; 134 start_h = i; 135 if( j==1 ) 136 start_pre = 2; 137 else if( j==H ) 138 start_pre = 0; 139 else if( i==1 ) 140 start_pre = 1; 141 else 142 start_pre = 3; 143 } 144 } 145 scanf("%c",&c); 146 } 147 step = 0; 148 } 149 150 int main() 151 { 152 // freopen("in","r",stdin); 153 // freopen("out","w",stdout); 154 155 int cas; 156 scanf("%d",&cas); 157 while( cas-- ){ 158 init(); ///初始化工作 159 dfs(start_h,start_w,start_pre,3); ///优先左拐 160 dfs(start_h,start_w,start_pre,1); ///优先右拐 161 bfs(start_h,start_w); ///最短步数 162 } 163 return 0; 164 }
递归效率太低了,这次深刻体会~