布线问题就是在 M×N 的方格阵列中,指定一个起点 a、一个终点 b,要求找到起点到终点的最短布线方案(最短路径)。
搜索从起点 a 开始,到目标点 b 结束。约束条件:有边相连且未成布线。
搜过过程:从起点 a 开始,将其作为一个扩展结点,沿 a 的上、下、左、右 4 个方向的相邻结点扩展。判断约束条件是否成立,如果成立,则放入活结点表中,并将这些方格标记为 1。接着从活结点表中取出队首结点作为下一个当前扩展节点,将其相邻且未标记的方格记为2。依此类推,一直继续到算法搜索到目标方格或活结点表为空为止。目标方格里的数据表示的就是布线长度,即最短路径。路径可以反向根据数字从 b 递减到 a 。
过程如下动画:
C++ 代码
#include <iostream>
#include <queue>
#include <cstdlib>
using namespace std;
typedef struct {
int row;
int col;
} Position;
bool findPath(Position start, Position finish, int &pathLen, Position* &path, int** grid, unsigned int m, unsigned int n) {
if((start.row==finish.row) && (start.col==finish.col)) {
pathLen = 0;
return true;
}
for(int i=0; i <= n+1; i++)//方格阵列上下围墙
grid[0][i] = grid[m+1][i] = -2;
for(int i=0; i <= m+1; i++)//方格阵列左右围墙
grid[i][0] = grid[i][n+1] = -2;
Position offset[4];
offset[0].row = 0;
offset[0].col = 1;
offset[1].row = 1;
offset[1].col = 0;
offset[2].row = 0;
offset[2].col = -1;
offset[3].row = -1;
offset[3].col = 0;
int numOfNbrs = 4;
Position here, nbr;
here.row = start.row;
here.col = start.col;
grid[start.row][start.col] = 0;
queue<Position> Q;
do {
for(int i=0; i < numOfNbrs; i++) {
nbr.row = here.row+offset[i].row;
nbr.col = here.col+offset[i].col;
if(grid[nbr.row][nbr.col] == -1) { //如果这方向还没有拓展
grid[nbr.row][nbr.col] = grid[here.row][here.col]+1;
Q.push(nbr);
}
if((nbr.row==finish.row) && (nbr.col==finish.col))
break;
}
if((nbr.row==finish.row) && (nbr.col==finish.col))
break;//完成布线
if(Q.empty())
return false;
here = Q.front();
Q.pop();
} while(true);
pathLen = grid[finish.row][finish.col];
path = new Position[pathLen];
here = finish;
for(int j=pathLen-1; j >= 0; j--) {
path[j] = here;
for(int i=0; i < numOfNbrs; i++) {
nbr.row = here.row+offset[i].row;
nbr.col = here.col+offset[i].col;
if(grid[nbr.row][nbr.col] == j)
break;
}
here = nbr;
}
return true;
}
int main() {
int m = 9, n = 7;
int** grid = new int*[m+2];
for(int i=0; i < m+2; i++)
grid[i] = new int[n+2];
for(int i=1; i <= m; i++)
for(int j=1; j <=n; j++)
cin >> grid[i][j];
Position start, finish;
start.row = 3;
start.col = 2;
finish.row = 6;
finish.col = 7;
int pathLen;
Position* path;
findPath(start, finish, pathLen, path, grid, m, n);
for(int i=1; i <= m; i++) {
for(int j=1; j <=n; j++) {
if(grid[i][j]==-2)
cout << "# ";
else {
int r;
for(r = 0; r < pathLen; r++) {
if(i==path[r].row && j==path[r].col) {
cout << "$ ";
break;
}
if(i == start.row && j == start.col) {
cout << "$ ";
break;
}
}
if(r == pathLen)
cout << "= ";
}
}
cout << endl;
}
return 0;
}