Keyboading 思路

0x01 前置芝士

还是先放个 link 吧。

所需知识点:BFS。

思维难度较高,实现简单。

0x02

题目大意:其实就是给你个图,按顺序走到相应的点,求所需最少步数(走到需要去的点会耗费一次步数)。特殊的,如果你要走的那个方向的字符和当前位一样,你会直接走的与当前位字符不一样的第一个点。

这不难想到直接去初始化a。

我们可以在一开始就暴力找出每个点的四个方向分别可以走到哪里。

然后就是一个简单的BFS了。

因为题意需要,我们可以再定义一个方向 \(5\),它表示当前点是否需要按下选择键。

然后再在BFS的队列中多保存一个走到当前点时,是在前往所求数组中那一个位置上的点的路上。

很显然每次前往某一个点时,重复走走过的点一定不划算,所以我们可以加个记忆数组 \(vis\)

如果下一个点的 \(vis\) 小于当前这个点再走。\(vis\) 可以看做是第几次经过,或者说可以看做是在去哪个点的路上。(都能做。

维护即可。

0x03

#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;

int read() {
    int x = 0, k = 1;
    char s = getchar();
    while (s < '0' || s > '9') {
        if (s == '-')
            k = -1;
        s = getchar();
    }
    while (s >= '0' && s <= '9') {
        x = (x << 3) + (x << 1) + (s ^ 48);
        s = getchar();
    }
    return x * k;
}

const int MAXN = 55;
const int MAXL = 1e4 + 5;
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
char mp[MAXN][MAXN], s[MAXL];
int r, c, len;

struct node {
    int x, y;
    node() {}
    node(int X, int Y) {
        x = X;
        y = Y;
    }
};
node con[MAXN][MAXN][4];
// con[i][j][k] 表示点 (i, j) 往 k 方向走会走到哪里。

void init() { // 暴力初始化
    for (int i = 1; i <= r; i++)
        for (int j = 1; j <= c; j++)
            for (int k = 0; k < 4; k++) {
                int x = i + dx[k], y = j + dy[k];
                if (x < 1 || x > r)
                    continue;
                if (y < 1 || y > c)
                    continue;
                while (!(mp[i][j] ^ mp[x][y]) && x <= r && y <= c && x >= 1 && y >= 1)
                    x = x + dx[k], y = y + dy[k];
                if (x >= 1 && x <= r && y >= 1 && y <= c)
                    con[i][j][k] = node(x, y);
            }
}

struct data {
    node now;
    int cnt, ans;
    data() {}
    data(node Now, int Cnt, int Ans) {
        now = Now;
        cnt = Cnt;
        ans = Ans;
    }
};

int vis[MAXN][MAXN];
void bfs() {
    memset(vis, -1, sizeof vis);
    queue<data> q;
    q.push(data(node(1, 1), 0, 0));
    // cnt 表示这是在去那个位置上的点的路径上。
    // ans 表示最终答案
    while (!q.empty()) {
        data t = q.front();
        q.pop();
        int x = t.now.x, y = t.now.y;
        for (int i = 0; i <= 4; i++) {
            if (i == 4) {
                if (mp[x][y] == s[t.cnt + 1] && vis[x][y] < t.cnt + 1) {
                    vis[x][y]++;
                    q.push(data(node(x, y), t.cnt + 1, t.ans + 1));
                    if (t.cnt + 1 == len) {
                        printf("%d\n", t.ans + 1);
                        return;
                    }
                }
            } else {
                node nxt = con[x][y][i];
                if (vis[nxt.x][nxt.y] < t.cnt && nxt.x && nxt.y) {
                    vis[nxt.x][nxt.y]++;
                    q.push(data(node(nxt.x, nxt.y), t.cnt, t.ans + 1));
                }
            }
        }
    }
}

int main() {
    r = read(), c = read();
    for (int i = 1; i <= r; i++) scanf("%s", mp[i] + 1);
    init();
    scanf("%s", s + 1);
    len = strlen(s + 1);
    len++;
    s[len] = '*';
    bfs();
    return 0;
}
posted @ 2020-11-28 16:10  STrAduts  阅读(59)  评论(0编辑  收藏  举报