本题使用BFS去求解,在写BFS的过程中要多保留步骤和是否捡到钥匙这两个信息。因为BFS并不是一个路径遍历的最后的(DFS),所以在每一个循环里面加步骤必然是不对的。所以需要在其结构体里面保存。还有就是这题独特之处在于钥匙和门的限制,也就是会出现捡到钥匙后还需要回头的情况和不需要钥匙直接到达重点两种情况。在这里只需要在没有钥匙的时候将其走过的路径变成D,在捡到钥匙后将其变成W就可以将这两种情况包含进去。
#include <bits/stdc++.h>

using namespace std;
struct Node{
    int x, y;
    int step;
    bool flag;
};
const int maxn = 500+10;
char ch[maxn][maxn];
int begin_x, begin_y;
int end_x, end_y;
queue<Node> q;
int mv[4][2] {
    {-1,0},
    {1,0},
    {0,1},
    {0,-1}
};

int main() {
    int H, W;
    cin>>H>>W;
    for (int i=1;i<=H;i++) {
        for (int j=1;j<=W;j++) {
            cin>>ch[i][j];
            if (ch[i][j]=='S') {
                begin_x = i;
                begin_y = j;
            }
        }
    }
    q.push({begin_x, begin_y, 0, false});
    int next_x, next_y;
    int ans = INT_MAX;
    while (q.size()) {
        Node n = q.front();
        q.pop();
        if (n.flag) {
            ch[n.x][n.y] = 'W';
        } else {
            ch[n.x][n.y] = 'D';
        }
        for (int i=0;i<4;i++) {
            next_x = n.x+mv[i][0];
            next_y = n.y+mv[i][1];
            if (ch[next_x][next_y]=='W') {
                continue;
            } 
            if (ch[next_x][next_y]=='.') {
                q.push({next_x, next_y, n.step+1, n.flag});
            }
            if (ch[next_x][next_y]=='K') {
                q.push({next_x, next_y, n.step+1, true});
            }
            if (ch[next_x][next_y]=='D') {
                if (n.flag==true)
                q.push({next_x, next_y, n.step+1, true});
            }
            if (ch[next_x][next_y]=='E') {
                ans = min(ans, n.step+1);
            }
        }
    }
    if (ans==INT_MAX)
        cout<<-1;
    else
    cout<<ans<<endl;
    return 0;
}