问题描述:
用户从屏幕输入m,n表示一个m*n的迷宫,0表示空地,1表示墙,给定起点的行,列;给定终点的行,列;输出最少到达目标的步数;
示例输入:
4 4
0 0 1 0
0 1 0 0
0 0 0 1
0 0 0 0
0 0
2 2
样例输出:
5
问题分析:
1.根据分支限界法基本思想(详见上篇分支限界博客)
(1)分支:当前位置每次有四种可能的走法上下左右,可分四个子状态;
(2)限界:若为墙,则不能走;若走过,则不能走;
2.确定输入输出:
迷宫的行列M,N;
迷宫的初始状态;
起点的坐标;
终点的坐标;
输出一个最小步数;
3.确定所需数据结构:
二维数组表示迷宫;
队列存放路径;
4.确定状态值:
迷宫中-2墙(为了计算与表示方便,将墙1置为-2,若为正常的额1表示,则需要多余的数据结构来记录某点是否走过),-1表示未走过,其余数字值表示从起点至当前位置所需步数;
方向:0-up, 1-down, 2-left, 3-right;
代码展示:
#include <iostream>
#include <queue>
using namespace std;
queue<int> q1;
int room[20][20];
int start, aim;
int m, n;
void readData()
{
int c, r;
cin >> m >> n;
for (int i(0); i < m; ++i)
{
for (int j(0); j < n; ++j)
{
cin >> room[i][j];
if (room[i][j] == 0)
room[i][j] = -1;
else
room[i][j] = -2;
}
}
cin >> r >> c;
start = r * n + c;
cin >> r >> c;
aim = r * n + c;
}
bool canmove(int u, int a)
{
int row, col;
row = u / n;
col = u % n;
//a: 0 up; 1 down; 2 left; 3 right;
switch(a)
{
case 0: row -= 1;break;
case 1: row += 1;break;
case 2: col -= 1;break;
case 3: col += 1;break;
default: break;
}
if (row >= 0 && row < n && col >= 0 && col < n)
if (room[row][col] != -2)
return true;
return false;
}
int moveto(int u, int a)
{
//a: 0 up; 1 down; 2 left; 3 right;
switch(a)
{
case 0: u -= n;break;
case 1: u += n;break;
case 2: u -= 1;break;
case 3: u += 1;break;
default: break;
}
return u;
}
int run()
{
int u, v;
while(!q1.empty())
{
u = q1.front();
q1.pop();
for (int i(0); i < 4; ++i)
{
if (canmove(u, i))
{
v = moveto(u, i);
if (v == aim)
return room[u / n][u % n] + 1;
else if (room[v / n][v % n] == -1)
{
q1.push(v);
room[v / n][v % n] = room[u / n][u % n] + 1;
}
}
}
}
return 0;
}
int main()
{
readData();
// initdata
q1.push(start);
room[start / n][ start % n] = 0;
cout << run() << endl;
return 0;
}