您的位置:首页 > 其它

实现迷宫和表达式计算问题

2017-12-13 16:05 501 查看
1.实现迷宫的递归非递归。

1)迷宫的非递归算法

//Maze.h
#pragma once
#include<iostream>
#include"windows.h"
#include<stack>
using namespace std;
struct Pos
{
int  row;
int  col;
};

template<size_t N>
class Maze
{
public:
/*Maze(int maze[]
)
{
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
_maze[i][j] = maze[i][j];
}
}
}*/
Maze(int* maze)
{
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
_maze[i][j] = maze[i*N + j];
}
}
}
void Print()
{
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
cout << _maze[i][j] << " ";
}
cout << endl;
}
}
bool CheckIsAccess(Pos pos)
{
//边界、是否为通路
if ((pos.row < N&&pos.row >= 0 && pos.col < N&&pos.col >= 0) && (_maze[pos.row][pos.col] == 0))
{
return true;
}
return false;
}
bool GetPath(Pos entry, stack<Pos>& path)
{
path.push(entry);
while (!path.empty())
{
//探测
Pos cur = path.top();
_maze[cur.row][cur.col] = 2;//走过的路标记为2
//判断是否到出口
if (cur.row == N - 1)
{
return true;
}
//上
Pos next = cur;
next.row = next.row + 1;
if (CheckIsAccess(next))
{
path.push(next);
continue;
}
//下
next = cur;
next.row = next.row - 1;
if (CheckIsAccess(next))
{
path.push(next);
continue;
}
//左
next = cur;
next.col = next.col - 1;
if (CheckIsAccess(next))
{
path.push(next);
continue;
}
//右
next = cur;
next.col = next.col + 1;
if (CheckIsAccess(next))
{
path.push(next);
continue;
}
//此路不通,回溯
path.pop();
}
return false;
}

protected:
int _maze

;
};


//Test.cpp
#include "Maze.h"
void TestMaze()
{
const size_t N = 10;
int maze

=
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }
};

Maze<10> mz((int*)maze);
//Maze<10> mz(maze);
mz.Print();
cout << "/******************************/" << endl;
Pos entry;
stack<Pos> path;
entry.row = 2;
entry.col = 0;
mz.GetPath(entry, path);
mz.Print();
}
int main()
{
TestMaze();
system("pause");
return 0;
}


运行结果如下:



2)迷宫的递归算法

bool GetPath_R(Pos cur, stack<Pos>& path)
{
path.push(cur);
//探测
_maze[cur.row][cur.col] = 2;//走过的路标记为2
//判断是否到出口
if (cur.row == N - 1)
{
return true;
}
//上
Pos next = cur;
next.row = next.row + 1;
if (CheckIsAccess(next))
{
if (GetPath_R(next, path))
{
return true;
}
}
//下
next = cur;
next.row = next.row - 1;
if (CheckIsAccess(next))
{
if (GetPath_R(next, path))
{
return true;
}
}
//左
next = cur;
next.col = next.col - 1;
if (CheckIsAccess(next))
{
if (GetPath_R(next, path))
{
return true;
}
}
//右
next = cur;
next.col = next.col + 1;
if (CheckIsAccess(next))
{
if (GetPath_R(next, path))
{
return true;
}
}
//此路不通
_maze[cur.row][cur.col] = 3;//返回的路程标记为3
return false;
}




递归算法解决迷宫问题的解法图如下:



当递归调用到点(8,2)时,没有可通行的点,递归函数会推出当前栈帧,返回到上一层栈帧中,如果还没有可通行的继续返回,直到(4,2)时(4,3)可通行就继续调用函数直到找到出口。

3)如何动态开辟二维数组

采用指针数组的方法,每个指针元素指向一块空间,如需要M*N大小的数组,可以先开长度为M大的指针数组,每个指针指向一个1 *N的一维数组。



int** _maze=new int*[M];
for(size_t i=0;i<M;i++)
{
_maze[i]=new int
;
}


2.实现迷宫的最优解问题。

上述解决迷宫方法存在的问题:

并不能遍历迷宫的所有通路,找到迷宫通路中最短的一条路径。并考虑如果迷宫中带有环路如何找到最短路径。

故而,提出解法如下:



代码如下:

bool CheckIsAccess(Pos cur, Pos next)
{
//1考虑边界;2是否为通路;3是否别人走过,自己没走过
if (next.row < N && next.row >= 0 && next.col < N && next.col >= 0  && (_maze[next.row][next.col] == 0 || _maze[cur.row][cur.col] < _maze[next.row][next.col]))
{
return true;
}
return false;
}
void GetShortPath(Pos cur, stack<Pos>& path, stack<Pos>& shortpath)
{
if (!path.empty())
{
Pos prev = path.top();
_maze[cur.row][cur.col] = _maze[prev.row][prev.col] + 1;//每走一步比前一个标记多1
}
path.push(cur);
//判断是否到出口
if (cur.row == N - 1)
{
if (shortpath.empty() || path.size() < shortpath.size())
{
shortpath = path;
}
}
//上
Pos next = cur;
next.row = next.row - 1;
if (CheckIsAccess(cur, next))
{
GetShortPath(next, path, shortpath);
}
//下
next = cur;
next.row = next.row + 1;
if (CheckIsAccess(cur, next))
{
GetShortPath(next, path, shortpath);
}
//左
next = cur;
next.col = next.col - 1;
if (CheckIsAccess(cur, next))
{
GetShortPath(next, path, shortpath);
}
//右
next = cur;
next.col = next.col + 1;
if (CheckIsAccess(cur, next))
{
GetShortPath(next, path, shortpath);
}
//此路不通
path.pop();
}


void TestMaze2()
{
const size_t N = 10;
int maze

=
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }
};

Maze<10> mz((int*)maze);
//Maze<10> mz(maze);
mz.Print();
cout << "/******************************/" << endl;
Pos entry;
stack<Pos> path;
stack<Pos> shortpath;
entry.row = 2;
entry.col = 0;
mz.GetShortPath(entry, path, shortpath);
mz.Print();
}


运行结果如下图所示:



path栈内如下图,同时解释了入口处设为2的过程



若:

int maze[10][10] =
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }
};


结果如下:



3.实现表达式计算问题。

1)将中缀表达式转换为后缀表达式



2)由后缀表达式计算值



代码如下:

//RPN.h
#pragma once
#include<iostream>
#include<stack>
#include<vector>
#include"assert.h"
using namespace std;
enum Cal_Type
{
OP_NUM,
OP_ADD,
OP_SUB,
OP_MUL,
OP_DIV,
};

struct Cell
{
Cal_Type _type; // 类型
int _value; // 值
};
class Calculator
{
public:
Calculator(Cell* exp, size_t n)
{
_rpn.resize(n);//改变容量,并初始化
for (size_t i = 0; i < n; i++)
{
_rpn[i] = exp[i];//若_rpn未初始化,[]会出错
}
}
int Count()
{
stack<int> s;
for (size_t i = 0; i < _rpn.size();++i)
{
if(_rpn[i]._type == OP_NUM)//是数值则入栈
{
s.push(_rpn[i]._value);
}
else if (_rpn[i]._type != OP_NUM)
{
int right = s.top();
s.pop();
int left = s.top();
s.pop();
switch (_rpn[i]._type)
{
case OP_ADD:
s.push(left + right);
break;
case OP_SUB:
s.push(left - right);
break;
case OP_MUL:
s.push(left * right);
break;
case OP_DIV:
s.push(left / right);
break;
default:
assert(false);
}
}
else
{
assert(false);
}
}
return s.top();
}
protected:
vector<Cell>  _rpn; // 表达式
};


测试代码如下:

#include"RPN.h"

int main()
{
Cell exp[] =
{
{OP_NUM, 2},
{OP_NUM, 3},
{OP_NUM, 4},
{OP_MUL, 0},
{OP_SUB, 0},
{OP_NUM, 5},
{OP_ADD, 0},
};
Calculator cal(exp, sizeof(exp)/sizeof(Cell));
cout << "计算结果:" << cal.Count() << endl;
system("pause");
return 0;
}


运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: