[題解] [BFS] [無AC代碼僅講解] CodeForces Gym 101755 H. Safe Path
VJudge題目:https://cn.vjudge.net/contest/279018#problem/K
即CodeForces Gym 101755 H. Safe Path : http://codeforces.com/gym/101755/problem/H
關於DFS連通塊的題解:https://www.cnblogs.com/Kaidora/p/10392641.html
關於BFS求數字的題解:https://www.cnblogs.com/Kaidora/p/10392293.html
為什麽不提供
而我寫的暴力都能到test 14才超時,實在不想再重寫了,再見。
如果你做過連通塊字符畫的題目,那麽這道題應該不難。
先說明題意:
輸入一個n行m列的字符畫,其中有起點S,終點F,怪物M,空地 . 。
輸入提供了怪物走動的步數。如果怪物能到達的位置視為不可通過,包括起始點。
現在問起點到終點需要多少步。
輸入輸出:
輸入n m d 代表 行 列 怪物步數 (2?≤?n*m?≤?20,0000,?0?≤?d?≤?20,0000)
輸入n*m字符畫
輸出步數
示例:
Input:
5 7 1 S.M...M ....... ....... M...M.. ......F
Output:
12
Input:
7 6 2 S..... ...M.. ...... .....M ...... M..... .....F
Output:
11
Input:
7 6 2 S..... ...M.. ...... ...... .....M M..... .....F
Output:
-1
Input:
4 4 2 M... .S.. .... ...F
Output:
-1
n*m=20,0000而不是n=m=20,000,char map[200002][200002]是開不了的。
讀入n,m後再建立map[n+2][m+2]則可以通過編譯。(請勿模仿!)
然後初始化,輸入。
先不要管起始點,把怪能到達的地方找出來。
結構體有三個成員x,y,step;
x,y是坐標,step是當前步數。
首先把字符畫中的M的坐標和步數0加入結構體隊列。
寫一個bfsMonster():
從隊列中取走一個結構體,得到坐標x,y,步數step。步數step==d則拋棄數據重新在隊列取結構體;(step==d表明這一格是最大步數了)
否則檢查地圖中相鄰的四格。如果這格非\0且不是M,就把字符刷為M,同時把這一格的坐標和步數step+1加入隊列。
隊列處理完你可以把地圖輸出,看看地圖中的M是不是擴散開的樣子。如第一例:
SMMM.MM
..M...M
M...M..
MM.MMM.
M...M.F
再暴力搜索S和F,記下坐標。沒有搜到表明被怪覆蓋了,可以直接輸出-1。
把S的坐標和步數0加入隊列,寫一個bfsPlayer():
進行與bfsMonster類似的操作,不過去掉step==d的檢查,改為坐標值檢查。
如果當前坐標x+y與F的坐標Fx+Fy只相差1,說明你搜到終點旁,可以輸出step+1了。
隊列處理完依然沒有搜到終點,說明終點被怪隔開了,輸出-1。
刷經過的路徑是必須要的,這樣可以防止重復搜索。如第一例:
SMMMPMM
PPMPPPM
MPPPMPP
MMPMMMP
MPPPM.F
附代碼參考。再次說明這個代碼會Runtime error,可能是map數組與結構體隊列太大爆掉的。希望這個代碼能啟發你。
(那四行整齊難看的代碼是新手早期作品,我懶得改,復制到0.3版還在用233)
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 /* 5 //結構體隊列實現 6 struct NodeQueue 7 { 8 short exist; 9 int x,y,step; 10 struct NodeQueue *next; 11 }head={0,0,0,0,0}; 12 struct NodeQueue *front=&head; 13 struct NodeQueue *back=&head; 14 struct NodeQueue *p=0; 15 struct NodeQueue* push(int x,int y,int step) 16 { 17 back->next=malloc( sizeof(struct NodeQueue) ); 18 back=back->next; 19 back->exist=1; 20 back->x=x,back->y=y,back->step=step; 21 back->next=0; 22 if(front==&head) 23 { 24 front=back; 25 head.next=0; 26 } 27 return back; 28 } 29 struct NodeQueue* pull() 30 { 31 if(front!=back) 32 { 33 struct NodeQueue *p; 34 p=front->next; 35 free(front); 36 front=p; 37 38 } 39 else if(front!=&head) 40 { 41 front=&head; 42 free(back); 43 back=front; 44 } 45 return front; 46 } 47 //over 48 */ 49 struct Node 50 { 51 short exist; 52 int x,y,step; 53 }que[200002]={{0,0,0,0}}; 54 struct Node *front=&que[0]; 55 struct Node *back=&que[0]; 56 void push(int x,int y,int step) 57 { 58 back++; 59 back->exist=1; 60 back->x=x,back->y=y,back->step=step; 61 if(front==&que[0]) 62 { 63 front=back; 64 } 65 } 66 void pull() 67 { 68 if(front==back) 69 { 70 front=&que[0]; 71 back=front; 72 } 73 else 74 { 75 front++; 76 } 77 } 78 79 int N,M,D; 80 int Sx=0,Sy=0,Fx=0,Fy=0; 81 int main() 82 { 83 scanf("%d%d%d",&N,&M,&D); getchar(); 84 char map[N+2][M+2]; memset(map,0,(N+2)*(M+2)*sizeof(char) ); 85 86 for(int n=1;n<=N;n++) 87 { 88 gets( &map[n][1] ); 89 for(int m=1;m<=M;m++) 90 { 91 if( map[n][m]==‘M‘ ) 92 { 93 push(n,m,0); 94 } 95 } 96 } 97 //輸入並完成‘M‘入隊 98 99 int Monster(int x,int y,int step,char map[N+2][M+2]); 100 for(;;) 101 { 102 Monster(front->x,front->y,front->step,map); 103 pull(); 104 if(back->exist==0)break; 105 } 106 //將地圖上怪能到達的點塗為怪 107 108 // for(unsigned n=1;n<=N;n++) 109 // puts( &map[n][1] ); 110 111 for(int n=1;n<=N;n++) 112 for(int m=1;m<=M;m++) 113 { 114 if( map[n][m]==‘S‘ ) Sx=n,Sy=m; 115 if( map[n][m]==‘F‘ ) Fx=n,Fy=m; 116 } 117 //找到起始點 118 119 int player(int x,int y,int step,char map[N+2][M+2]); 120 if( Sx && Sy && Fx && Fy ) 121 { 122 push(Sx,Sy,0); 123 while(1) 124 { 125 if( player(front->x,front->y,front->step,map) ) 126 return 0; 127 pull();if(back->exist==0)break; 128 } 129 } 130 //刷路徑直到找到F 131 132 // for(unsigned n=1;n<=N;n++) 133 // puts( &map[n][1] ); 134 135 puts("-1"); 136 return 0; 137 } 138 139 int Monster(int x,int y,int step,char map[N+2][M+2]) 140 { 141 if( step==D )return 0; 142 if( map[x-1][y]!=‘M‘ && map[x-1][y]){ map[x-1][y]=‘M‘; push(x-1,y,step+1); } 143 if( map[x+1][y]!=‘M‘ && map[x+1][y]){ map[x+1][y]=‘M‘; push(x+1,y,step+1); } 144 if( map[x][y-1]!=‘M‘ && map[x][y-1]){ map[x][y-1]=‘M‘; push(x,y-1,step+1); } 145 if( map[x][y+1]!=‘M‘ && map[x][y+1]){ map[x][y+1]=‘M‘; push(x,y+1,step+1); } 146 return 0; 147 } 148 149 int player(int x,int y,int step,char map[N+2][M+2]) 150 { 151 if( (x==Fx || y==Fy) && (x+y==Fx+Fy-1 || x+y==Fx+Fy+1) ){ printf("%d\n",step+1); return 1; } 152 if( map[x-1][y]==‘.‘ ){ map[x-1][y]=‘P‘; push(x-1,y,step+1); } 153 if( map[x+1][y]==‘.‘ ){ map[x+1][y]=‘P‘; push(x+1,y,step+1); } 154 if( map[x][y-1]==‘.‘ ){ map[x][y-1]=‘P‘; push(x,y-1,step+1); } 155 if( map[x][y+1]==‘.‘ ){ map[x][y+1]=‘P‘; push(x,y+1,step+1); } 156 return 0; 157 } 158 /* 159 int QueueAll() 160 { 161 struct NodeQueue *p=front; 162 if(p->exist==0)return 0; 163 while(1) 164 { 165 printf("%d,%d,%d\n",p->x,p->y,p->step); 166 p=p->next; 167 if(p==0)return 0; 168 } 169 p=0; 170 } 171 */View Code
[題解] [BFS] [無AC代碼僅講解] CodeForces Gym 101755 H. Safe Path