1.问题定义及需求分析
假设有一个NxM的迷宫,有一个入口,有一个出口。作为程序员你操纵一只老鼠,让它找到一条路径。并将路径输出出来。
输入形式:N M,地图,入口坐标和出口坐标
输出形式:路径
2.概要设计
用一个动态二维bool数组来初始化这个迷宫,采用STL栈存储路径,数组的二维下标代表路径,故栈的元素采用STL里的pair。之后将栈全部取出存入一个动态数组,循环将动态数组输出。
3.详细设计
地图存储及初始化:因为只有墙和路两种值,而地图又是确定的,故采用动态的bool数组。值得注意的是,因为边界条件,如果在边界,就不能四面都判断,故在四边上了一堵墙,所以实际空间是(N+2)x(M+2)。(1代表墙,0代表路)
代码:bool **p=new bool *[n+2];
for (int i = 0; i <= n+1; ++i)
p[i] = new bool[m + 2];
for (int i = 0; i <= m+1; ++i)
{
p[0][i] = 1;
p[n+1][i] = 1;
}
for (int i = 1; i < n; ++i)
{
p[i][m+1]=p[i][0] = 1;
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
cin >> p[i][j];
寻迹:先将起点压入栈,按照深度优先遍历(即每次从栈顶找,不断将可走的节点压入栈,并把该节点的bool值改为1,使它不能再遍历,然后将该节点无路可走,就将元素弹出,如果有路径,则栈最后一定是非空的),出循环条件为到达终点或栈已经空了。
代码:while (!path.empty()&&now!=pathend)
{
if (!p[now.first + 1][now.second])
{
p[now.first + 1][now.second] = 1;
++now.first;
path.push(now);
++step;
}
else if (!p[now.first][now.second+1])
{
p[now.first][now.second + 1] = 1;
++now.second;
path.push(now);
++step;
}
else if (!p[now.first -1][now.second])
{
p[now.first - 1][now.second]=1;
--now.first;
path.push(now);
++step;
}
else if (!p[now.first ][now.second-1])
{
p[now.first][now.second - 1] = 1;
--now.second;
path.push(now);
++step;
}
else
{
--step;
path.pop();//当前无路可走往回走
}
}
4.调试分析:
对所遇问题的解决方法及分析:
主要使用了VS的调试器跟踪寻迹循环,第一次发现bool数组初始化小了,为[n+1]x[m+1]。而不是[n+2]x[m+2];
还有if (!p[now.first + 1][now.second])
{
p[now.first + 1][now.second] = 1;
++now.first;
path.push(now);
++step;
}
else if (!p[now.first][now.second+1])
{
p[now.first][now.second + 1] = 1;
++now.second;
path.push(now);
++step;
}
这语句因为4个都差不多,我就写了一个后面复制了,调试过程中,发现有一个有个地方p的下标没改。
算法的时空分析及改进思想:
时空分析:
因为算法是遍历一个栈,最好情况下是一条路直接走到终点,既不用后退,最长路又铁定小于NxM,所以最好情况是o(n^2)。
最坏情况下,走了很多的死路才到终点,但考虑到对同一个位置最多来的时候走一次,退的时候又走一次所以最多为2xNxM,复杂度是o(n^2)。
实际上,不可能地图每个节点都走,所以会明显好于o(n^2)。
改进思想:
实际在编写不断检验的时候已经做了很多改进,比如入栈的操作,起初是4个if,后来改为了if,else if,即只有当前路走到了死,才去找新的,省去了一些栈的操作。还有考虑程序可读性,又删除了一些多余语句。
经验和体会:
希望以后自己能大概构思好了程序,再编写。在逻辑上先足够严谨,不要急于求成。细心一些。
5.使用说明and6.测试结果:
7.附录
void riddle()
{
int n,m;//迷宫大小
cout << "请输入迷宫大小:" << endl;
cin >> n>>m;
cout << "请输入迷宫:" << endl;
bool **p=new bool *[n+2];
for (int i = 0; i <= n+1; ++i)
p[i] = new bool[m + 2];
for (int i = 0; i <= m+1; ++i)
{
p[0][i] = 1;
p[n+1][i] = 1;
}
for (int i = 1; i < n; ++i)
{
p[i][m+1]=p[i][0] = 1;
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
cin >> p[i][j];//初始化地图
stack<pair<int, int>> path;//存储路径
pair<int, int> *paths;//存储栈的数组
int step = 1;//记录路径长度
cout << "请输入起点:" << endl;
pair<int, int> now,pathend;//记录当前位置和终点
cin >> now.first >> now.second;
path.push(now);
p[now.first][now.second] = 1;
cout << "请输入终点" << endl;
cin >> pathend.first >> pathend.second;
while (!path.empty()&&now!=pathend)
{
if (!p[now.first + 1][now.second]) //下
{
p[now.first + 1][now.second] = 1;
++now.first;
path.push(now);
++step;
}
else if (!p[now.first][now.second+1]) //右
{
p[now.first][now.second + 1] = 1;
++now.second;
path.push(now);
++step;
}
else if (!p[now.first -1][now.second]) //上
{
p[now.first - 1][now.second]=1;
--now.first;
path.push(now);
++step;
}
else if (!p[now.first ][now.second-1]) //左
{
p[now.first][now.second - 1] = 1;
--now.second;
path.push(now);
++step;
}
else
{
--step;
path.pop();//当前无路可走往回走
}
}
if (path.empty())
{
cout << "不存在路径"<<endl;
return;
}
paths = new pair<int, int>[step];
int i = step;
while (!path.empty())
{
paths[--i] = path.top();//将栈取出
path.pop();
}
cout << "找到路径长度为" << step << "的路径:" << endl;
for (int i = 0; i < step - 1; ++i)
cout << '(' << paths[i].first << ',' << paths[i].second << ')' << "->";
cout << '(' << paths[step-1].first << ',' << paths[step-1].second << ')' << endl;
for (int i = 0; i <= n + 1; ++i)
delete p[i];
delete p;
delete paths;
}