[ 题解 ] [ 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


为什么不提供AC代码,因为我的BFS提交上去Runtime error on test 5

而我写的暴力都能到test 14才超时,实在不想再重写了,再见。


如果你做过连通块字符画的题目,那么这道题应该不难。


先说明题意:

输入一个nm列的字符画,其中有起点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,000char map[200002][200002]是开不了的。

读入nm后再建立map[n+2][m+2]则可以通过编译。(请勿模仿!)


然后初始化,输入。


先不要管起始点,把怪能到达的地方找出来。


结构体有三个成员xystep

xy是坐标,step是当前步数。


首先把字符画中的M的坐标和步数0加入结构体队列。


写一个bfsMonster()

从队列中取走一个结构体,得到坐标xy,步数step。步数step==d则抛弃数据重新在队列取结构体;(step==d表明这一格是最大步数了)

否则检查地图中相邻的四格。如果这格非\0且不是M,就把字符刷为M,同时把这一格的坐标和步数step+1加入队列。


队列处理完你可以把地图输出,看看地图中的M是不是扩散开的样子。如第一例:

SMMM.MM
..M...M
M...M..
MM.MMM.
M...M.F

 

再暴力搜索SF,记下坐标。没有搜到表明被怪覆盖了,可以直接输出-1


S的坐标和步数0加入队列,写一个bfsPlayer()

进行与bfsMonster类似的操作,不过去掉step==d的检查,改为坐标值检查。

如果当前坐标x+yF的坐标Fx+Fy只相差1,说明你搜到终点旁,可以输出step+1了。

队列处理完依然没有搜到终点,说明终点被怪隔开了,输出-1


刷经过的路径是必须要的,这样可以防止重复搜索。如第一例:

SMMMPMM
PPMPPPM
MPPPMPP
MMPMMMP
MPPPM.F

 

 

 

 

 

附代码参考。再次说明这个代码会Runtime error,用C++队列也一样。可能是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

 

posted @ 2019-02-20 14:55  Kaidora  阅读(355)  评论(0编辑  收藏  举报