题意: 如图,注意可能有不止一个朋友,遇到有守卫的区域先要花1s解决守卫才能走下一步,求救出Angel的最短时间。
算法:BFS
问题:一开始用vis数组的部分改变来处理打架的情况,实际上vis数组是不能轻易改变的,会出问题,可以通过增加结构体里包含的变量来表示是否在打架的状态;处理完打架就不能再走了,所以需要continue;之后屡屡tle,找了好久,问了别人,最后发现是while(scanf)里的!=EOF没写……,以后一定要仔细啊。
思路:因为起点可能不止一个,就把起始点与终点互换,BFS找出最近(耗时最少)的起点。
代码:ac
#include<bits/stdc++.h>
using namespace std;
char Map[210][210];
int sx[210], sy[210], ex, ey;
int n, m;
int cnt = 0;/*朋友数*/
struct pos {
int x;
int y;
int time;
int f;/*储存是否打架的状态,即该点有没有守卫*/
};
int vis[210][210];/*是否进过队*/
int dir[4][2] = { {-1,0},{1,0},{0,1},{0,-1} };
void bfs();
int main()
{
while (scanf("%d%d", &n, &m)!=EOF) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
cin >> Map[i][j];
vis[i][j] = 0;
if (Map[i][j] == 'r') {
cnt++;
sx[cnt] = i;
sy[cnt] = j;
}
if (Map[i][j] == 'a') {
ex = i,ey = j;
vis[i][j] = 1;
}
}
bfs();
}
return 0;
}
void bfs()
{
queue<pos>qu;
pos cur, nex;
cur.x = ex, cur.y = ey;
cur.time = 0;
cur.f = 0;
qu.push(cur);
while (!qu.empty()) {
cur = qu.front();
qu.pop();
if (Map[cur.x][cur.y] == 'r') {
printf("%d\n", cur.time);
return;
}
nex.time = cur.time + 1;
if (cur.f) {/*有守卫的情况单独讨论*/
nex.x = cur.x, nex.y = cur.y;
nex.f = 0;
qu.push(nex);
continue;/*注意需要跳到下一次,因为时间已经加一了*/
}
nex.f = 0;
for (int i = 0; i < 4; i++) {
if (Map[cur.x + dir[i][0]][cur.y + dir[i][1]] != '#' && vis[cur.x + dir[i][0]][cur.y + dir[i][1]] == 0) {
if (cur.x + dir[i][0] >= 1 && cur.x + dir[i][0] <= n && cur.y + dir[i][1] >= 1 && cur.y + dir[i][1] <= m) {
nex.x = cur.x + dir[i][0];
nex.y = cur.y + dir[i][1];
vis[nex.x][nex.y] = 1;
if (Map[nex.x][nex.y] == 'x')nex.f = 1;
qu.push(nex);
}
}
}
}
printf("Poor ANGEL has to stay in the prison all his life.\n");
}