回溯法
基本思想:对一个包括有很多个结点,每个结点有若干个搜索分支的问题,把原问题分解为多若干个子问题求解的算法;当搜索到某个结点发现无法再继续搜索下去时,就让搜索过程回溯(回退)到该节点的前一个结点,继续搜索该节点外的其他尚未搜索的分支;如果发现该结点无法再搜索下去,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程;这样的搜索过程一致进行到搜索到问题的解或者搜索完了全部可搜索分子没有解存在为止。
#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;
}
运行结果:(这种无终止条件的递归直接粗暴,会遍历所有给出的路径。但在有多个出口的情况时,还是无法得出最优路径)
有待完善^_^