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
为什么不提供AC代码,因为我的BFS提交上去Runtime error on test 5;
而我写的暴力都能到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,用C++队列也一样。可能是map数组与结构体队列太大爆掉的。希望这个代码能启发你。
(那四行整齐难看的代码是新手早期作品,我懒得改,复制到0.3版还在用233)
如果大佬能指出这里存在什么问题,感谢不尽!
1 #include2 #include <string.h> 3 #include 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 */