迷宫(回溯,递归)

回溯法

基本思想:对一个包括有很多个结点,每个结点有若干个搜索分支的问题,把原问题分解为多若干个子问题求解的算法;当搜索到某个结点发现无法再继续搜索下去时,就让搜索过程回溯(回退)到该节点的前一个结点,继续搜索该节点外的其他尚未搜索的分支;如果发现该结点无法再搜索下去,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程;这样的搜索过程一致进行到搜索到问题的解或者搜索完了全部可搜索分子没有解存在为止。
#include <iostream>
#include <stack>
using namespace std;

#define MAX_ROW 10
#define MAX_COL 10

struct Seat
{
    int x;
    int y;
};

class Maze
{
public:
    Maze(int array[MAX_ROW][MAX_COL])
    {
        for(int i = 0; i < MAX_ROW; i++)
        {
            for(int j = 0; j <MAX_COL; j++)
            {
                map[i][j] = array[i][j];
            }
        }
    }

    bool IsPass(const Seat& s)
    {
        if((s.x >= 0 && s.x < MAX_ROW) &&
            (s.y >= 0 && s.y < MAX_COL))
            return 1 == map[s.x][s.y];
        return 0;
    }

    void PassMaze(stack<Seat>& s, Seat& next)
    {
        s.push(next);
        map[next.x][next.y] = 2;

        while(!s.empty())
        {
            if(s.top().x == 0 || s.top().x == MAX_ROW ||
               s.top().y == 0 || s.top().y == MAX_ROW)
            {
                cout<<"找到出口"<<endl;
                return;
            }

            next = s.top();
            Seat up = {next.x-1, next.y};
            Seat left = {next.x, next.y-1};
            Seat right = {next.x, next.y+1};
            Seat down = {next.x+1, next.y};

            if(IsPass(up))
            {
                s.push(up);
                map[up.x][up.y] = 2;
                continue;
            }

            if(IsPass(left))
            {
                s.push(left);
                map[left.x][left.y] = 2;
                continue;
            }

            if(IsPass(right))
            {
                s.push(right);
                map[right.x][right.y] = 2;
                continue;
            }

            if(IsPass(down))
            {
                s.push(down);
                map[down.x][down.y] = 2;
                continue;
            }

            map[next.x][next.y] = 3;
            s.pop();
            next = s.top();
        }
        cout<<"没有出口"<<endl;
    }

    void PrintMap()
    {
        for(int i = 0; i < MAX_ROW; i++)
        {
            for(int j = 0; j < MAX_COL; j++)
            {
                cout<<map[i][j]<<" ";
            }
            cout<<endl;
        }
    }

private:
    int map[MAX_ROW][MAX_COL];
};


int main()
{
    int mapArr[MAX_ROW][MAX_COL] = 
        { 
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 
            {1, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 0, 1, 1, 1, 1, 0, 0, 0}, 
            {0, 0, 0, 0, 0, 0, 1, 0, 0, 0} 
        };
    Seat entry = {9, 6};
    stack<Seat> s;
    Maze m(mapArr);
    m.PassMaze(s, entry);
    m.PrintMap();

    return 0;
}

运行结果:(存在缺陷)
这里写图片描述

递归

#include <iostream>
using namespace std;

#define MAX_ROW 10
#define MAX_COL 10

struct Seat
{
    int x;
    int y;
};

class Maze
{
public:
    Maze(int array[MAX_ROW][MAX_COL])
    {
        for(int i = 0; i < MAX_ROW; i++)
        {
            for(int j = 0; j <MAX_COL; j++)
            {
                map[i][j] = array[i][j];
            }
        }
    }

    bool IsPass(const Seat& s)
    {
        if((s.x >= 0 && s.x < MAX_ROW) &&
            (s.y >= 0 && s.y < MAX_COL))
            return 1 == map[s.x][s.y];
        return 0;
    }

    bool PassMaze(const Seat& s)
    {
        if(s.x >= MAX_ROW || s.x < 0 || s.y >= MAX_COL || s.y < 0)
            return true;

        if(IsPass(s))
        {
            map[s.x][s.y] = 2;

            Seat up = {s.x-1, s.y};
            Seat left = {s.x, s.y-1};
            Seat right = {s.x, s.y+1};
            Seat down = {s.x+1, s.y};
            if(PassMaze(up))
            {
                return true;
            }

            else if(PassMaze(left))
            {
                return true;
            }

            else if(PassMaze(right))
            {
                return true;
            }

            else if(PassMaze(down))
            {
                return true;
            }
            else
            {
                map[s.x][s.y] = 3;
            }
        }
        return false;
    }

    void PrintMap()
    {
        for(int i = 0; i < MAX_ROW; i++)
        {
            for(int j = 0; j < MAX_COL; j++)
            {
                cout<<map[i][j]<<" ";
            }
            cout<<endl;
        }
    }

private:
    int map[MAX_ROW][MAX_COL];
};


int main()
{
    int mapArr[MAX_ROW][MAX_COL] = 
        { 
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 
            {1, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 0, 1, 1, 1, 1, 0, 0, 0}, 
            {0, 0, 0, 0, 0, 0, 1, 0, 0, 0} 
        };
    Seat s = {9, 6};
    Maze m(mapArr);
    m.PassMaze(s);
    m.PrintMap();

    return 0;
}

运行结果:(这种求法和类似于回溯法找出口,根据你代码搜素方式只会找到一条出口,然后就会退出)
这里写图片描述

无返回值的递归求解

#include <iostream>
using namespace std;

#define MAX_ROW 10
#define MAX_COL 10

struct Seat
{
    int x;
    int y;
};

class Maze
{
public:
    Maze(int array[MAX_ROW][MAX_COL])
    {
        for(int i = 0; i < MAX_ROW; i++)
        {
            for(int j = 0; j <MAX_COL; j++)
            {
                map[i][j] = array[i][j];
            }
        }
    }

    bool IsPass(const Seat& s)
    {
        if((s.x >= 0 && s.x < MAX_ROW) &&
            (s.y >= 0 && s.y < MAX_COL))
            return 1 == map[s.x][s.y];
        return 0;
    }

    void PassMaze(const Seat& s)
    {
        if(IsPass(s))
        {
            map[s.x][s.y] = 2;

            Seat up = {s.x-1, s.y};
            Seat left = {s.x, s.y-1};
            Seat right = {s.x, s.y+1};
            Seat down = {s.x+1, s.y};
            if(IsPass(up))
            {
                PassMaze(up);
            }

            if(IsPass(left))
            {
                PassMaze(left);
            }

            if(IsPass(right))
            {
                PassMaze(right);
            }

            if(IsPass(down))
            {
                PassMaze(down);
            }
        }

    }

    void PrintMap()
    {
        for(int i = 0; i < MAX_ROW; i++)
        {
            for(int j = 0; j < MAX_COL; j++)
            {
                cout<<map[i][j]<<" ";
            }
            cout<<endl;
        }
    }

private:
    int map[MAX_ROW][MAX_COL];
};


int main()
{
    int mapArr[MAX_ROW][MAX_COL] = 
        { 
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 
            {1, 0, 0, 0, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 
            {0, 0, 0, 1, 1, 1, 1, 0, 0, 0}, 
            {0, 0, 0, 0, 0, 0, 1, 0, 0, 0} 
        };
    Seat s = {9, 6};
    Maze m(mapArr);
    m.PassMaze(s);
    m.PrintMap();

    return 0;
}

运行结果:(这种无终止条件的递归直接粗暴,会遍历所有给出的路径。但在有多个出口的情况时,还是无法得出最优路径)
这里写图片描述
有待完善^_^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值