Tank走迷宫(某比赛决赛题)

具体题目有些忘了。题目大意是这样的,一个tank从A点出发,到目的地B,只能“+”“-“交叉走,走过的位置不能再走。求最短步数。典型BFS题目。用C++做相对要简单一些,毕竟有STL…

Tank.h

/*迷宫栗子图,建立txt文本,放在E盘下
 * A + - + - *
 * + - + - + *
 * - + - + - *
 * - + + + - *
 * B + - + + *
*/


#ifndef TANK_H_
#define TANK_H_ 1

#include 
#include 
#include 

using std::queue;
using std::vector;

enum Dire {Left = 0, Down, Right, Up, None};

struct Node
{
    int      _cur;
    Dire    _dire;  //之前的方向
};

class Tank
{
private:
    queue<vector > pos;
public:
    Tank(const char** tank_map, int n);        // tank_map为存入地图
    ~Tank();

    //test
public:
    //void get_all() const;
    int get_step() const;   //返回步数
    bool trace();        // 驱动
private:
    bool finish() const;      // 判断是否走到目的点
    bool can_move_left() const;
    bool can_move_down() const;
    bool can_move_right() const;
    bool can_move_up() const;
    void get_pos();
private:
    bool**        _map_had_move;    //已经走过
    bool**        _map_plus_minus;  //正-true,负-false
    const char**  _map;       // 指向地图
    int           _start;     // 开始位置
    int           _cur;       // 当前位置
    int           _end;       // 目的位置
    bool          _move;      // 当前位置的正负
    Dire          _drec;      // 当前方向
    int           _N;         // N * N数组大小
    int           _step;      // 记录步数
};

#endif // TANK_H_

Tank.cpp

#include "tank.h"
#include 

Tank::Tank(const char** tank_map, int n)
{
    _N = n;
    _map = tank_map;
    get_pos();
    _move = true;
    _step = 0;
    _drec = None;

    Node tmp;
    tmp._cur = _cur;
    tmp._dire = None;

    vector t;
    t.push_back(tmp);
    pos.push(t);

    _map_had_move = new bool* [_N];
    for (int i = 0; i < _N; ++i)
        _map_had_move[i] = new bool [_N];
    for (int i = 0; i < _N; ++i)
        for (int j = 0; j < _N; ++j)
            _map_had_move[i][j] = false;
    _map_had_move[_start/_N][_start%_N] = true;      //标记起点已走
}

Tank::~Tank()
{
    for (int i = 0; i < _N; ++i)
    {
        delete [] _map_had_move[i];
        delete [] _map_plus_minus[i];
    }
}

inline bool Tank::finish() const
{
    return _cur == _end;
}

bool Tank::can_move_left() const
{
    if ((_drec == None || Left != _drec) && _cur%_N-1 >= 0 && (_map[_cur/_N][_cur%_N-1] == 'A' || _map[_cur/_N][_cur%_N-1] == 'B'))
        return true;

    if ((_drec == None || Left != _drec) && _cur%_N-1 >= 0 && !_map_had_move[_cur/_N][_cur%_N-1])
    {
        if (_map[_cur/_N][_cur%_N] == 'A' || _map[_cur/_N][_cur%_N] == 'B')
            return true;
        else
            return _map_plus_minus[_cur/_N][_cur%_N-1] ^ _map_plus_minus[_cur/_N][_cur%_N];
    }
    return false;
}

bool Tank::can_move_down() const
{
    if ((_drec == None || Down != _drec) && _cur/_N+1 < _N && (_map[_cur/_N+1][_cur%_N] == 'A' || _map[_cur/_N+1][_cur%_N] == 'B'))
        return true;

    if ((_drec == None || Down != _drec) && _cur/_N+1 < _N && !_map_had_move[_cur/_N+1][_cur%_N])
    {
        if (_map[_cur/_N][_cur%_N] == 'A' || _map[_cur/_N][_cur%_N] == 'B')
            return true;
        else
            return _map_plus_minus[_cur/_N+1][_cur%_N] ^ _map_plus_minus[_cur/_N][_cur%_N];
    }
    return false;
}

bool Tank::can_move_right() const
{
    if ((_drec == None || Right != _drec) && _cur%_N+1 < _N && (_map[_cur/_N][_cur%_N+1] == 'A' || _map[_cur/_N][_cur%_N+1] == 'B'))
        return true;

    if ((_drec == None || Right != _drec) && _cur%_N+1 < _N && !_map_had_move[_cur/_N][_cur%_N+1])
    {
        if (_map[_cur/_N][_cur%_N] == 'A' || _map[_cur/_N][_cur%_N] == 'B')
            return true;
        else
            return _map_plus_minus[_cur/_N][_cur%_N+1] ^ _map_plus_minus[_cur/_N][_cur%_N];
    }
    return false;
}

bool Tank::can_move_up() const
{
    if ((_drec == None || Up != _drec) && _cur/_N-1 >= 0 && (_map[_cur/_N-1][_cur%_N] == 'A' || _map[_cur/_N-1][_cur%_N] == 'B'))
        return true;

    if ((_drec == None || Up != _drec) && _cur/_N-1 >= 0 && !_map_had_move[_cur/_N-1][_cur%_N])
    {
        if (_map[_cur/_N][_cur%_N] == 'A' || _map[_cur/_N][_cur%_N] == 'B')
            return true;
        else
            return _map_plus_minus[_cur/_N-1][_cur%_N] ^ _map_plus_minus[_cur/_N][_cur%_N];
    }
    return false;
}

void Tank::get_pos()
{
    _map_plus_minus = new bool* [_N];
    for (int i = 0; i < _N; ++i)
        _map_plus_minus[i] = new bool [_N];

    for (int i = 0; i < _N * _N; ++i)
    {
        if (_map[i/_N][i%_N] == 'A')
        {
            _cur = _start = i;
            _map_plus_minus[i/_N][i%_N] = true;
        }
        if (_map[i/_N][i%_N] == 'B')
        {
            _end = i;
            _map_plus_minus[i/_N][i%_N] = true;
        }
        if (_map[i/_N][i%_N] == '+')
            _map_plus_minus[i/_N][i%_N] = true;
        if (_map[i/_N][i%_N] == '-')
            _map_plus_minus[i/_N][i%_N] = false;
    }
}

bool Tank::trace()
{
    while (!pos.empty())
    {
        vector tmp = pos.front();
        pos.pop();

        vector::iterator iter = tmp.begin();

        vector push_to_pos;

        while(iter != tmp.end())
        {
            Node t = *iter;

            _cur = t._cur;
            _drec = t._dire;

            if (finish())       //判断是否到达了目的地
                return true;

            if (can_move_left())
            {
                t._cur = _cur - 1;
                t._dire = Right;
                push_to_pos.push_back(t);
                _map_had_move[t._cur/_N][t._cur%_N] = true;
            }
            if (can_move_down())
            {
                t._cur = _cur + _N;
                t._dire = Up;
                push_to_pos.push_back(t);
                _map_had_move[t._cur/_N][t._cur%_N] = true;
            }
            if (can_move_right())
            {
                t._cur = _cur + 1;
                t._dire = Left;
                push_to_pos.push_back(t);
                _map_had_move[t._cur/_N][t._cur%_N] = true;
            }
            if (can_move_up())
            {
                t._cur = _cur - _N;
                t._dire = Down;
                push_to_pos.push_back(t);
                _map_had_move[t._cur/_N][t._cur%_N] = true;
            }
            iter++;
            //输出轨迹
            /*std::cout << "t._cur: " << t._cur << "t._dire: " << t._dire << std::endl;
            for (int i = 0; i < _N; ++i)
                for (int j = 0; j < _N; ++j)
                {
                    std::cout << _map_had_move[i][j] << " ";
                    if (j == _N - 1)
                        std::cout << std::endl;
                }*/
        }
        if (!push_to_pos.empty())
            pos.push(push_to_pos);
        ++_step;
    }
    return false;
}

int Tank::get_step() const
{
    return _step;
}

main.cpp

#include "tank.h"
#include 

int main()
{
    using std::ifstream;

    using std::cout;
    using std::endl;

    ifstream read_file("E:\\test.txt");
    if(read_file.is_open())
    {
        int n;
        read_file >> n;

        char** tank_map;
        tank_map = new char* [n];
        for (int i = 0; i < n; ++i)
            tank_map[i] = new char [n];

        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                read_file >> tank_map[i][j];

        Tank tank((const char**)tank_map, n);

        if (tank.trace())
            cout << "step: " << tank.get_step() << endl;
        else
            cout << -1 << endl;
    }

    return 0;
}

当时没做出来,后来想想才做出来(泪。。)

你可能感兴趣的:(算法)