传送门
//中文题面就不说了.
//提示 : 既然是最短时间, 第一反应肯定是bfs, 但是这道题需要你对bfs的理解要深刻一点. 如果单纯以最短去搜索, 遇到x时间就加2, @就加1, 然后去找. 这样肯定会WA的. 因为这样找只是找到的最短路径下的时间, 并不是最短时间, 所以我们不能以路径来扩充下一个节点, 而是应该以时间来扩充下一个节点, 即队列中推出来的是目前到这个点的最短时间. 所以bfs搜索的最短是要看题目来决定的, 这个要求你要对bfs有一些内涵理解.
AC Code
/** @Cain*/
const int maxn=2e2+5;
char s[maxn][maxn];
bool vis[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int n,m;
int sx,sy;
struct node
{
int x,y,step;
node(int x=0,int y=0,int step=0):x(x),y(y),step(step){};
bool operator < (const node &a) const {
return a.step < step;
} //为了保证时间在先出来, 所以我们用优先队列来维护它的优先级.
};
void bfs()
{
priority_queue<node>q;
q.push(node{sx,sy,0});
vis[sx][sy] = true;
while(!q.empty()){ //除了时间的优先级,其他的跟普通bfs一样的套路.
node t = q.top();
q.pop();
if(s[t.x][t.y] == 'a') {
printf("%d\n",t.step);
return ;
}
for(int i=0;i<4;i++){
int xx = t.x + dx[i];
int yy = t.y + dy[i];
if(xx<=0 || xx >n || yy<=0 || yy >m || vis[xx][yy]) continue;
if(s[xx][yy] == '#') continue;
vis[xx][yy] = true;
if(s[xx][yy] == 'x') q.push(node{xx,yy,t.step+2});
else q.push(node{xx,yy,t.step+1});
}
}
printf("Impossible\n");
}
void solve()
{
scanf("%d%d",&n,&m);
Fill(s,0);
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
Fill(vis,false);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j] == 'r'){
sx = i;
sy = j;
}
}
}
bfs();
}