Skip to content

11281: 【原1281】蹦蹦跳跳

题目

题目描述

author: Chen Xutong 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1281

Description

cxt出发了,他要去找时光机,可是距离好远,因为他生存在远古时期,木有轮船,飞机,大炮什么的。于是只能跳回去 = =。地图是一个矩形,可以划分成M × N个方格。一些格子是岩石,还有一些沼泽,其余的只是美丽、纯净、湛蓝的水。因为cxt不会游泳 = =。cxt每次站在一块岩石上,想跳到另一块岩石上,他只能从一块岩石跳到另一块岩石上,既不能跳到水里,也不能跳到沼泽里。因为cxt有惊人的弹跳能力,他的跳法很像象棋中的马步:每次跳跃可以横移M1格,纵移M2格,或纵移M1格,横移M2格,最多有八个方向可供移动选择。请计算cxt到达终点的最小步数,输入数据保证终点是一定可达的。

Input Format

第一行:四个用空格分开的整数:M,N,M1和M2, 1 ≤ M, N ≤ 30,1 ≤ M1 ≤ 30,1 ≤ M2 ≤ 30,M1 ≠ M2

第二行到M + 1行:第i + 1行有N个用空格分开的整数,描述了池塘第i行的状态:0 为水,1 为岩石,2 为沼泽,3 为起点,4 为终点。

Output Format

第一行:从起点到终点的最少步数

Sample Input

4 5 1 2
1 0 1 0 1
3 0 2 0 4
0 1 2 0 0
0 0 0 1 0

Sample Output

2

数据说明

先跳到 1 行 3 列的岩石上,再跳到终点,需要 2 步

BugenZhao's solution

//
// Created by BugenZhao on 2019/5/17.
//
//
// Created by BugenZhao on 2019/4/5.
//

#ifndef SBL_BQUEUE_H
#define SBL_BQUEUE_H


#include <iostream>

template<typename Item>
class BQueue {
    class Node {
    public:
        Item item;
        Node *next;

        explicit Node(const Item &item, Node *next = nullptr) : item(item), next(next) {}

        explicit Node(Node *next = nullptr) : next(next) {}

        virtual ~Node() = default;
    };

    int N;
    Node *first;
    Node *last;

public:
    BQueue() {
        N = 0;
        first = last = nullptr;
    }

    bool isEmpty() const {
        return N == 0;
    }

    int size() const {
        return N;
    }

    void enqueue(Item item) {
        if (N == 0) {
            first = new Node{item};
            last = first;
        } else {
            Node *tmp = last;
            last = new Node{item};
            tmp->next = last;
        }
        ++N;
    }

    Item dequeue() {
        Item item = first->item;
        Node *tmp = first;
        first = first->next;
        if (N == 1) last = nullptr;
        delete tmp;
        --N;
        return item;
    }

    Item getFirst() const {
        return first->item;
    }

    Item getLast() const {
        return last->item;
    }

    void clear() {
        Node *tmp;
        while (first != nullptr) {
            tmp = first;
            first = first->next;
            delete tmp;
        }
        N = 0;
        first = last = nullptr;
    }

    virtual ~BQueue() {
        Node *tmp;
        while (first != nullptr) {
            tmp = first;
            first = first->next;
            delete tmp;
        }
    }

private:
    class Iterator {
        Node *it;
        Node *first;
        Node *last;
    public:

        Iterator(Node *first, Node *last) :
                it(first), first(first), last(last) {}

        bool hasNext() const {
            return it != nullptr;
        }

        Item &next() {
            Node *p = it;
            it = it->next;
            return p->item;
        }

        const Item &next() const {
            Node *p = it;
            it = it->next;
            return p->item;
        }
    };

public:
    Iterator iterator() const {
        return Iterator(first, last);
    }
};


#endif //SBL_BQUEUE_H


#include <iostream>
#include <string>

using std::ios, std::cin, std::cout, std::endl, std::string;

class Point {
public:
    int x, y;

    Point(int x = 0, int y = 0) :
            x(x), y(y) {}
};


int height[30][30];
Point from[30][30];
bool flag[30][30];
int X0, Y0, X, Y;


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int m, n, m1, m2;
    cin >> m >> n >> m1 >> m2;
    int dx[] = {m1, m1, m2, m2, -m1, -m1, -m2, -m2};
    int dy[] = {m2, -m2, m1, -m1, m2, -m2, m1, -m1};

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> height[i][j];
            if (height[i][j] == 3) X0 = i, Y0 = j;
            else if (height[i][j] == 4) X = i, Y = j;
        }
    }

    BQueue<Point> q;
    q.enqueue(Point(X0, Y0));
    from[X0][Y0] = {-1, -1};
    flag[X0][Y0] = true;

    while (!q.isEmpty()) {
        Point point = q.dequeue();
        for (int i = 0; i < 8; ++i) {
            int xx = point.x + dx[i];
            int yy = point.y + dy[i];
            if (xx < 0 || xx >= m || yy < 0 || yy >= n || flag[xx][yy]) continue;
            if (height[xx][yy] == 0 || height[xx][yy] == 2) continue;
            if (height[xx][yy] == 4) {
                int ans = 1;
                int x = point.x, y = point.y;
                while (true) {
                    if (x == X0 && y == Y0) break;
                    ++ans;
                    Point tmp = from[x][y];
                    x = tmp.x, y = tmp.y;
                }
                cout << ans << endl;
                return 0;
            }
            if (height[xx][yy] == 1) {
                flag[xx][yy] = true;
                q.enqueue(Point(xx, yy));
                from[xx][yy] = Point(point.x, point.y);
            }
        }
    }
}

ligongzzz's solution

#include "iostream"
#include "cstdio"
#include "cstring"
using namespace std;

template <class T>
class my_queue {
public:
    T queue_[50000];
    int start = 0, end = 0;
    int mod = 50000;
    void clear() {
        start = 0;
        end = 0;
        memset(queue_, 0, sizeof(queue_));
    }
    bool empty() const {
        return end - start == 0;
    }
    T front() const {
        return queue_[start % mod];
    }
    void pop() {
        ++start;
    }

    void push(const T& val) {
        queue_[(end++) % mod] = val;
    }
    int size() {
        return end - start;
    }
};

class position {
public:
    int distance = 0;
    int pos_x = 0, pos_y = 0;

    position() = default;
    position(int dis, int x, int y) :distance(dis), pos_x(x), pos_y(y) {}
};

int map_data[49][49] = { 0 };

bool visited[49][49] = { 0 };
int dx[8], dy[8];
int n, m;

my_queue<position> queue_data;
int bfs(int start_x, int start_y, int end_x, int end_y) {
    queue_data.clear();
    memset(visited, 0, sizeof(visited));
    position start_point(0, start_x, start_y);
    queue_data.push(start_point);
    visited[start_x][start_y] = true;

    while (!queue_data.empty()) {
        auto temp = queue_data.front();
        queue_data.pop();

        if (temp.pos_x == end_x && temp.pos_y == end_y) {
            return temp.distance;
        }

        for (int i = 0; i < 8; ++i) {
            if (temp.pos_x + dx[i] >= 0 && temp.pos_x + dx[i] < m &&
                temp.pos_y + dy[i] >= 0 && temp.pos_y + dy[i] < n &&
                !visited[temp.pos_x + dx[i]][temp.pos_y + dy[i]]
                && map_data[temp.pos_x + dx[i]][temp.pos_y + dy[i]] != 0
                && map_data[temp.pos_x + dx[i]][temp.pos_y + dy[i]] != 2) {
                position next_point(temp.distance + 1, temp.pos_x + dx[i], temp.pos_y + dy[i]);
                queue_data.push(next_point);
                visited[next_point.pos_x][next_point.pos_y] = true;
            }
        }
    }
    return -1;
}


int main() {
    int m1, m2;
    scanf("%d %d %d %d", &m, &n, &m1, &m2);

    dx[0] = m1, dy[0] = m2;
    dx[1] = m1, dy[1] = -m2;
    dx[2] = -m1, dy[2] = m2;
    dx[3] = -m1, dy[3] = -m2;
    dx[4] = m2, dy[4] = m1;
    dx[5] = m2, dy[5] = -m1;
    dx[6] = -m2, dy[6] = m1;
    dx[7] = -m2, dy[7] = -m1;

    int start_x, start_y, end_x, end_y;

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            scanf("%d", &map_data[i][j]);
            if (map_data[i][j] == 3) {
                start_x = i;
                start_y = j;
            }
            else if (map_data[i][j] == 4) {
                end_x = i;
                end_y = j;
            }
        }
    }

    cout << bfs(start_x, start_y, end_x, end_y);

    return 0;
}

skyzh's solution

#include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <queue>

using namespace std;

bool visited[30][30] = {0};
int MAP[30][30];

int M, N, M1, M2;
int sx, sy, ex, ey;

inline bool is_ok(int x, int y) {
    if (x >= 0 && y >= 0 && x < M && y < N) {
        if (MAP[x][y] == 1 || MAP[x][y] == 3 || MAP[x][y] == 4) {
            return true;
        }
    }
    return false;
}

int ans = INT_MAX;

int dir[8][2] = {0};

struct Record {
    int x, y, step;

    Record(int x, int y, int step) : x(x), y(y), step(step) {};

    Record() {};
};

template<typename T>
struct Queue {
    T *x;
    int head, tail;

    Queue(int cap) : head(0), tail(0) { x = new T[cap]; }

    void push(const T &d) { x[tail++] = d; }

    void pop() { ++head; }

    T &front() { return x[head]; }

    T &rear() { return x[tail - 1]; }

    bool empty() { return head == tail; }
};

int bfs() {
    Queue<Record> q(10000);
    Record c(sx, sy, 0), p;
    q.push(c);
    while (!q.empty()) {
        p = q.front();
        q.pop();
        if (p.x == ex && p.y == ey) {
            return p.step;
        }
        for (int d = 0; d < 8; d++) {
            int _x = p.x + dir[d][0];
            int _y = p.y + dir[d][1];
            if (is_ok(_x, _y)) {
                if (!visited[_x][_y]) {
                    visited[_x][_y] = true;
                    q.push(Record(_x, _y, p.step + 1));
                }
            }
        }
    }
}

int main() {
    cin >> M >> N >> M1 >> M2;
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            cin >> MAP[i][j];
            if (MAP[i][j] == 3) {
                sx = i;
                sy = j;
            }
            if (MAP[i][j] == 4) {
                ex = i;
                ey = j;
            }
        }
    }
    dir[0][0] = M1;
    dir[0][1] = M2;
    dir[1][0] = M1;
    dir[1][1] = -M2;
    dir[2][0] = -M1;
    dir[2][1] = M2;
    dir[3][0] = -M1;
    dir[3][1] = -M2;
    dir[4][1] = M1;
    dir[4][0] = M2;
    dir[5][1] = M1;
    dir[5][0] = -M2;
    dir[6][1] = -M1;
    dir[6][0] = M2;
    dir[7][1] = -M1;
    dir[7][0] = -M2;
    cout << bfs() << endl;
    return 0;
}

yyong119's solution

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int MAX_N = 35;
struct node {
    node(int a, int b, int p) {
        x = a; y = b; step = p;
    };
    int x, y, step;
};

int main() {

    int n, m, N, M;
    cin >> n >> m >> N >> M;
    const int movement[8][2] = { {N, M}, {M, N}, {-N, M}, {-M, N}, {-N, -M}, {-M, -N}, {N, -M}, {M, -N} };
    int a[MAX_N][MAX_N]; memset(a, 0, sizeof(a));
    bool visited[MAX_N][MAX_N]; memset(visited, false, sizeof(visited));
    queue<node> que;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
            cin >> a[i][j];
            if (a[i][j] != 1 && a[i][j] != 4) visited[i][j] = true;
            if (a[i][j] == 3) que.push(node(i, j, 0));
        }
    bool found = false;
    int ans;
    while (!que.empty()) {
        node now = que.front();
        for (int i = 0; i < 8; ++i) {
            int nextx = now.x + movement[i][0], nexty = now.y + movement[i][1];
            if (nextx < 0 || nextx >= n || nexty < 0 || nexty >= m) continue;
            if (!visited[nextx][nexty]) {
                if (a[nextx][nexty] == 4) {
                    found = true;
                    ans = now.step + 1;
                    break;
                }
                que.push(node(nextx, nexty, now.step + 1));
                visited[nextx][nexty] = true;
            }
        }
        if (found) break;
        que.pop();
    }
    cout << ans << endl;
    return 0;
}