期末考试之考试传纸条
Time Limit: 1000 ms Case Time Limit: 1000 ms Memory Limit: 32 MB
Description
平时不努力,考试得着急呐。传说中的BT监考老师竟然搬来了信号屏蔽工具,手机不管用啦有木有。不过这难不到大家,cxlove见证了同学们使用传统的作弊方式----传纸条,纸条得从A同学传到B同学处,在一个N*M的教室里,零散着坐着一些同学,监考老师游荡在教室某些位置,能否成功将纸条传到B同学处,且不被老师发现。每一次传纸条不能斜传,只能传给前后左右四个同学,监考老师的监视范围为相邻的八个位置,当纸条传到老师监视范围内就会被逮住了,纸条传到空位置处时传送失败。 帮cxlove计算下最少需要多少时间才能完成传纸条。
Input
多组测试数据
第一行两个整数,N,M(1<=N,M<=100),分别表示教室有N*M个位置接下来N行,每行M个字符,表示教室的情况
'A'表示纸条的初始位置,'B'表示纸条的目标位置,'.'表示一般同学的位置,'#'表示当前位置没有人坐,'T'表示监考老师。(可能有多个监考老师)
第一行两个整数,N,M(1<=N,M<=100),分别表示教室有N*M个位置接下来N行,每行M个字符,表示教室的情况
'A'表示纸条的初始位置,'B'表示纸条的目标位置,'.'表示一般同学的位置,'#'表示当前位置没有人坐,'T'表示监考老师。(可能有多个监考老师)
Output
输出仅一个整数,表示需要的最少时间传到B同学处
如果不能传达,输出-1
如果不能传达,输出-1
Sample Input
Original | Transformed |
5 5 A.T.. .#..# ..... ####. ....B 1 5 A.T.B
Sample Output
Original | Transformed |
8 -1
Source
cxlove
——————————————————————帅气分割线——————————————————————
思路:这道题跟Hero in Maze那道题基本是一样的,都是最裸的bfs,只是多了一点东西。监考老师。话说想起来高考,监考老师什么的,监考就监考吧,咱没有怨言,问题是还要交监考费!这就说不通了,我不想让你监考了,不交钱了,行不?你监考,还问我要钱,又不是我请你来的。这种费用应当是完善自己教育体制的成本,不应当是考生的投资吧!咳咳,跑偏了……首先考虑监考老师周围这个问题。一旦我在输入的时候,输入了一个监考老师,那就意味着它和它周围的八个结点不能访问。但是问题来了,不能访问并不意味着不能设置另一个监考老师。有点像红色警戒里的光棱塔,当下一个光棱塔处于这个光棱塔攻击范围内,防御范围虽然牺牲了一小部分但是就没有盲点了。我们利用vis[ ][ ]数组解决。因为我们在输入地图的时候,是不会判断该结点是否有访问标记的。输入的时候就在监考老师范围的结点上设置访问标记即可。
代码如下:
——————————————————————帅气分割线——————————————————————
思路:这道题跟Hero in Maze那道题基本是一样的,都是最裸的bfs,只是多了一点东西。监考老师。话说想起来高考,监考老师什么的,监考就监考吧,咱没有怨言,问题是还要交监考费!这就说不通了,我不想让你监考了,不交钱了,行不?你监考,还问我要钱,又不是我请你来的。这种费用应当是完善自己教育体制的成本,不应当是考生的投资吧!咳咳,跑偏了……首先考虑监考老师周围这个问题。一旦我在输入的时候,输入了一个监考老师,那就意味着它和它周围的八个结点不能访问。但是问题来了,不能访问并不意味着不能设置另一个监考老师。有点像红色警戒里的光棱塔,当下一个光棱塔处于这个光棱塔攻击范围内,防御范围虽然牺牲了一小部分但是就没有盲点了。我们利用vis[ ][ ]数组解决。因为我们在输入地图的时候,是不会判断该结点是否有访问标记的。输入的时候就在监考老师范围的结点上设置访问标记即可。
代码如下:
#include <stdio.h>
#include <memory.h>
#define LIM nx>0&&nx<=n&&ny>0&&ny<=m
int q[10010];//建立队列
int mat[110][110], dis[110][110];
bool vis[110][110];
int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, 1, -1};
int n, m, sx, sy, ox, oy;
char s[110];
int bfs(int x, int y){
int fron = 0, rear = 0;
int u = x * 1000 + y;
vis[x][y] = 1;
dis[x][y] = 0;
q[rear++] = u;//起点进队
while(fron < rear){
u = q[fron++];//结点更新为当前队首
x = u / 1000; y = u % 1000;
for(int d = 0; d < 4; d++){//注意此处是d<4,表示上右下左四个方向,这是传纸条的方向
int nx = x + dx[d], ny = y + dy[d];
if(LIM && mat[nx][ny] && !vis[nx][ny]){
int v = nx * 1000 + ny;
q[rear++] = v;//偏移处结点进队
vis[nx][ny] = 1;
dis[nx][ny] = dis[x][y] + 1;//距离多1
if(nx == ox&&ny == oy)
return dis[nx][ny];//完成任务
}
}
}
return -1;
}
int main(){
int i, j, t;
while(scanf("%d%d", &n, &m) != EOF){
memset(mat, 0, sizeof(mat));
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i++){//这次的地图下标是从1开始的
scanf("%s", s);
for(j = 1; j <= m; j++){
switch(s[j-1]){
case 'A':mat[i][j] = 1;sx = i; sy = j; break;
case 'B':if(!vis[i][j]) {mat[i][j] = 1;ox = i; oy = j;} break;
case '.':if(!vis[i][j]) {mat[i][j] = 1;} break;
case '#':if(!vis[i][j]) {mat[i][j] = 0;} break;
case 'T':vis[i][j] = 1; for(int d = 0; d < 8; d++) vis[i+dx[d]][j+dy[d]] = 1; break;
}
}
}
t = bfs(sx, sy);
printf("%d\n", t);
}
return 0;
}