BFS:
当碰到岔道口时,依次访问从该岔道口出发能直接到达的所有节点,并用队列存储待访问节点。
注意点:
(1)在BFS中要始终把握的一个关键是“每个节点只入队一次”,故一定要注意设置的inqueue数组是用来标记其是否入过队而不是是否被访问过,也即当其入队后即将标志修改为true而不是出队后再进行修改。
(2)我认为这道题是对BFS非常典型的应用。与矩阵结合考察,那么为了方便入队可以设置struct结构体来存储节点坐标。但注意只是在入队时再为节点赋值即可,其它辅助数组中依然直接用坐标操作(开始时我以为在主函数输入后就要用节点存储起来 导致结构非常乱)。
(3)另外,对于一些求最小步数的题目也很适合用BFS来做。因为BFS是通过层次的顺序来遍历,因此可以从起点S开始计算遍历的层数,当到达一个终点时就是需要求解的最小步数。
参照了《算法笔记》的一些思路又结合了自己的理解。
我觉得书中对一个节点周围相邻节点遍历时,使用三个数组
int X[6] = { 0,0,0,0,1,-1 };
int Y[6] = { 0,0,1,-1,0,0 };
int Z[6] = { 1,-1,0,0,0,0 };
for (int i = 0; i < 6; i++)
int newX = temp.x + X[i], newY = temp.y + Y[i], newZ = temp.z + Z[i];
的方法非常值得借鉴。
int m, n, l, t;
int rec[1300][130][70] = { 0 }; //记录各坐标在立方体中的序号
int X[6] = { 0, 0, 0, 0, 1, -1 };
int Y[6] = { 0,0,1,-1,0,0 };
int Z[6] = { 1,-1,0,0,0,0 };
bool visited[1300][130][70]= { false };
struct cNode
{
int x;
int y;
int z;
}cube[1010];
queue<cNode> q;
//判断某一节点是否超出了立方体范围
bool judge(int x, int y, int z)
{
if (x >= 0 && x < m&&y>=0 && y < n&&z>=0 && z < l)
return true;
else
return false;
}
void BFS(cNode cn,int &sum)
{
q.push(cn);
visited[cn.x][cn.y][cn.z] = true;
while (!q.empty())
{
cNode temp = q.front();
q.pop();
sum += 1;
//遍历其相邻元素
for (int i = 0; i < 6; i++)
{
int newX = temp.x + X[i], newY = temp.y + Y[i], newZ = temp.z + Z[i];
if (judge(newX,newY,newZ))
{
if (rec[newX][newY][newZ] == 1 && visited[newX][newY][newZ] == false)
{
cNode newC;
newC.x = newX;
newC.y = newY;
newC.z = newZ;
visited[newX][newY][newZ] = true;
q.push(newC);
}
}
}
}
}
int main()
{
scanf("%d %d %d %d", &m, &n, &l, &t);
int count = 0;
for (int i = 0; i < l; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < n; k++) {
scanf("%d", &rec[j][k][i]);
}
int res = 0;
//遍历立方体
for (int i = 0; i < l; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < n; k++)
{
int sum = 0;
cNode newC;
//某节点还未被访问
if (visited[j][k][i] == false && rec[j][k][i]== 1) {
newC.x = j, newC.y = k, newC.z = i;
BFS(newC, sum);
}
if (sum >= t)
res += sum;
}
cout << res;
}