啊,被FDU无住宿无补贴劝退了,985终究一场梦,只好拿起自己学校的教材了
我们这本教材比较经典的就是电路布线问题了,估计和这方面成果不错有点关系。其实我今天仔细看了看发现这不就是迷宫的路径搜索问题吗……主要的思想还是深度优先搜索、回溯法……
参考了教材上的做法以后,发现其实思路都差不多,只不过我和它的标记和存储方法不同。我的做法是,初始化时用-2标记障碍点,用-1标记可布线点,用0标记起点,其它的依然是使用队列来搜索可布线点,但使用栈来存储路径,这样输出时正好是从起点到终点。
#include <cstdio>
#include <queue>
#include <stack>
using namespace std;
const int NumOfNbr = 4; //四个方向搜索,根据需要可改成八方向
const int GridOfRow = 7; //行
const int GridOfCol = 7; //列
int grid[GridOfRow+2][GridOfCol+2]; //加两行墙便于操作
struct Position{
int x;
int y;
}dir[NumOfNbr] = { {-1,0},{0,-1},{1,0},{0,1} }; //上左下右
void showLayout()
{
for(int i = 1; i <= GridOfRow; ++i){
for(int j = 1; j <= GridOfCol; ++j){
printf("%2d ", grid[i][j]);
}
printf("\n");
}
printf("\n");
}
// 可布线点-1,障碍物-2,起点处0
void initGird(Position start)
{
for(int i = 0; i <= GridOfRow+1; ++i)
for(int j = 0; j <= GridOfCol+1; ++j){
if( i==0 || j==0 || i==GridOfRow+1 || j==GridOfCol+1 )
grid[i][j] = -2;
else
grid[i][j] = -1;
}
printf("请输入障碍物坐标点,输入\"0,0\"结束:\n");
int x, y;
while( scanf("%d,%d",&x,&y) && !(x==0&&y==0) ){
if( (x<=0||x>GridOfRow) || (y<=0||y>GridOfCol) ){
printf("超出布线范围!重新输入!\n");
continue;
}
grid[x][y] = -2;
}
grid[start.x][start.y] = 0; //起点处标记为0
}
int FindPath(Position start, Position end, stack<Position>& path)
{
if( start.x==end.x && start.y==end.y )
return 0;
if( (start.x<=0||start.x>GridOfRow) || (start.y<=0||start.y>GridOfCol) ||
(end.x<=0 ||end.x>GridOfRow) || (end.y<=0 || end.y>GridOfCol) )
return -1;
initGird(start);
showLayout();
Position here = start, nby;
queue<Position> que;
bool isFind = false;
// 深度搜索路径
do{
// 各个方向的点
for(int i = 0; i < NumOfNbr; ++i)
{
nby.x = here.x + dir[i].x;
nby.y = here.y + dir[i].y;
// 可布线点
if( grid[nby.x][nby.y] == -1 ){
grid[nby.x][nby.y] = grid[here.x][here.y] + 1;
if( nby.x==end.x && nby.y==end.y ){
isFind = true;
break;
}
que.push(nby);
}
}
if( isFind )
break;
if( que.empty() )
return -1; // 找不到路径
else{
here = que.front(); // 弹出队首结点,继续搜索
que.pop();
}
}while( true );
// 回溯路径
here = end;
int pathLength = grid[end.x][end.y];
for(int len = pathLength-1; len >= 0; --len){
path.push(here);
for(int i = 0; i < NumOfNbr; ++i){
nby.x = here.x + dir[i].x;
nby.y = here.y + dir[i].y;
if( grid[nby.x][nby.y] == len )
break;
}
grid[here.x][here.y] = 0; //标记为0,便于观察最短路径
here = nby;
}
path.push(here); //别忘了补上起点
showLayout();
return pathLength;
}
int main(void)
{
Position start = {3,2}, end = {4,6};
stack<Position> path;
int length = FindPath(start, end, path);
printf("最短路径如下,长度为%d\n", length);
while( !path.empty() ){
Position p = path.top();
path.pop();
printf("(%d,%d)->", p.x, p.y);
}
return 0;
}
//For test
//1,3
//2,3
//2,4
//3,5
//4,4
//4,5
//5,5
//5,1
//6,1
//6,2
//6,3
//7,1
//7,2
//7,3
//0,0