胜利大逃亡(bfs)

题目描述:

Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.

魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1.

 

 

 

Input

输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙.(如果对输入描述不清楚,可以参考Sample Input中的迷宫描述,它表示的就是上图中的迷宫)

特别注意:本题的测试数据非常大,请使用scanf输入,我不能保证使用cin能不超时.在本OJ上请使用Visual C++提交.

 

 

Output

对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1.

 

 

Sample Input

1
3 3 4 20
0 1 1 1
0 0 1 1
0 1 1 1
1 1 1 1
1 0 0 1
0 1 1 1
0 0 0 0
0 1 1 0
0 1 1 0

 

 

Sample Output

 

11

 

主人公每次行走仅能走到上、下、左、右、前、后与主人公所在点相邻的位置、

即从(x,y,z)点行走至(x-1,y,z)、(x+1,y,z)、(x,y+1,z)、(x,y-1,z)、(x,y,z+1)、(x,y,z-1)六个点的其中一个。在这其中还存在着一些墙。

由于可以由任意一个点经过一秒的行走进入下一个点,所以由任意一个状态(x,y,z,t)可以扩展得到下面六个状态

(x-1,y,z,t+1)、(x+1,y,z,t+1)、

(x,y+1,z,t+1)、(x,y-1,z,t+1)、

(x,y,z+1,t+1)、(x,y,z-1,t+1)

先由根结点扩展出所有深度为 1 的结点,再由每一个深度为 1 的结点扩展出所有深度为 2 的结点,依次类推。

即便这样所需查找的状态还是非常得多,最坏情况下,因为每个结点都能扩展出六个新结点,那么仅走了 10 步,其状态数就会达到 6 的十次方,需要大量的时间才能依次遍历完这些状态。那么,我们必须采取相应的措施来制约状态的无限扩展。这个措施被称为剪枝

若有状态(x,y,z,t),其中 t 不是从起点到达(x,y,z)的最短时间,那么我们所要查找的答案必不可能由该状态进行
若干次扩展后得到。

为了防止对无效状态的搜索,我们需要一个标记数组 mark[x][y][z],当已经得到过包含坐标(x,y,z)的状态后,即把 mark[x][y][z]置为 true,当下次再由某状态扩展出包含该坐标的状态时,则直接丢弃,不对其进行任何处理。

平面的走动:
原点:0,0  
向下:1,0
向上:-1,0
向右:0,1 
向左:0,-1

三维的走动:
原点:
0,0,0
向下:0,1,0
向上:0,-1,0
向右:0,0,1 
向左:0,0,-1

从第0层走向第一层 
升高:1,0,0
降低:-1,0,0 
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;

int maze[51][51][51];// 储存迷宫 0代表路,1代表墙
bool mark[51][51][51]; // 1代表已经去过 0代表没去过

int a, b, c, t; //输入数据(先是第0块,然后是第1块,第2块......第a块),每块输入数据有B行,每行有C个正整数


typedef struct Now {
    int x, y, z;
    int t;
} Now;

queue<Now> q;


void printNow(Now& a) {
    cout << "pos: zyx:" << a.z << " " << a.y << " " << a.x << " t :" << a.t << endl;
}

void markNow(Now& a) {
    cout << "mark: zyx:" << a.z << " " << a.y << " " << a.x << " t :" << a.t << endl;

}

int bfs(int z, int y, int x) {
//从第z层,第y行  第x个元素开始  走到 c b a

//清空queue
    while(!q.empty()) {
        q.pop();
    }


    Now start;
    start.z = z;
    start.y = y;
    start.x = x;
    start.t = 0;


    Now father;
    Now child;

    q.push(start);
    while(!q.empty()) {
        father = q.front();
        q.pop();// 父亲出来,接下来的6个孩子进去

        // printNow(father);

        if (father.z == a && father.y == b && father.x == c) {
            return father.t;
        }


        // WASD // 穿层
        //上
        if (father.y - 1 >= 1 && maze[father.z][father.y - 1][father.x] == 0 && mark[father.z][father.y - 1][father.x] == 0 ) {
            child = father;
            child.y --;
            child.t ++;
            mark[child.z][child.y][child.x] = 1;
            //markNow(child);
            q.push(child);
        }
        //下
        if (father.y + 1 <= b && maze[father.z][father.y + 1][father.x] == 0 && mark[father.z][father.y + 1][father.x] == 0 ) {
            child = father;
            child.y ++;
            child.t ++;
            mark[child.z][child.y][child.x] = 1;
            //markNow(child);
            q.push(child);
        }
        //左
        if (father.x - 1 >= 1 && maze[father.z][father.y][father.x - 1] == 0 && mark[father.z][father.y][father.x - 1] == 0 ) {
            child = father;
            child.x --;
            child.t ++;
            mark[child.z][child.y][child.x] = 1;
            //markNow(child);
            q.push(child);
        }
        // 右
        if (father.x + 1 <= c && maze[father.z][father.y][father.x + 1] == 0 && mark[father.z][father.y][father.x + 1] == 0 ) {
            child = father;
            child.x ++;
            child.t ++;
            mark[child.z][child.y][child.x] = 1;
            // markNow(child);
            q.push(child);
        }

        //前
        if (father.z - 1 >= 1 && maze[father.z - 1][father.y][father.x] == 0 && mark[father.z - 1][father.y][father.x] == 0 ) {
            child = father;
            child.z --;
            child.t ++;
            mark[child.z][child.y][child.x] = 1;
            //markNow(child);
            q.push(child);
        }

        //后
        if (father.z + 1 <= a && maze[father.z + 1][father.y][father.x] == 0 && mark[father.z + 1][father.y][father.x] == 0 ) {
            child = father;
            child.z ++;
            child.t ++;
            mark[child.z][child.y][child.x] = 1;
            //markNow(child);
            q.push(child);
        }


    }

    return -1;

}




//打印出来
void show() {
    for (int i = 1; i <= a; i ++) {
        for (int j = 1; j <= b; j++) {
            for (int k = 1; k <= c; k++) {
                cout << maze[i][j][k] << "  ";
            }
            cout << endl;

        }
        cout << endl;
    }
    cout << endl;
}

int main() {
    int caseNum;
    cin >> caseNum;
    for (int caseNo = 1; caseNo <= caseNum; caseNo ++) {
        cin >> a >> b >> c >> t; // a层 b行  每行c个元素 // 3 3 4
        for (int i = 1; i <= a; i++) {
            for (int j = 1; j <= b; j++) {
                for (int k = 1; k <= c; k++) {
                    scanf("%d",&maze[i][j][k]) ;
                    mark[i][j][k] = 0;
                }

            }

        }

        //show();
        // 从1 1  1到 a b c
        int res = bfs(1, 1, 1);
        if (res != -1 && res<= t) {
            cout << res << endl;
        } else {
            cout << -1 << endl;
        }





    }




}

#include <iostream>
#include <queue>
using namespace std;

bool maze[51][51][51];
bool mark[51][51][51];
int a,b,c;// a块数据  // 每块为 b * c  // b行 C列
int time;

typedef struct Now {
	int z,y,x;
	int t;
} Now;

queue<Now> q;


int bfs() {
	while(!q.empty()) {
		q.pop();
	}

	Now chu;
	chu.z = chu.y = chu.x = 1;
	chu.t = 0;
	mark[1][1][1] = 1;

	Now father;
	Now child;


	q.push(chu);
	while(!q.empty()) {
		father = q.front();
		q.pop();
		// 父亲出来  孩子进去


		// 上 y--
		if (father.y - 1 >= 1 && maze[father.z][father.y-1][father.x] == 0 && mark[father.z][father.y-1][father.x] == 0) {
			child = father;
			child.y--;
			child.t++;

			if (child.t > time) {
				// 大于时间,就不加入了
			} else if (child.z == a && child.y == b && child.x == c && child.t <= time) {
				return child.t;// 到出口了
			} else {
				mark[child.z][child.y][child.x] = 1;
				q.push(child);
			}

		}
		// 下 y++
		if (father.y + 1 <= b && maze[father.z][father.y+1][father.x] == 0 && mark[father.z][father.y+1][father.x] == 0) {
			child = father;
			child.y++;
			child.t++;

			if (child.t > time) {
				// 大于时间,就不加入了
			} else if (child.z == a && child.y == b && child.x == c && child.t <= time) {

				return child.t;// 到出口了
			} else {
				mark[child.z][child.y][child.x] = 1;
				q.push(child);
			}

		}
		// 左 x--
		if (father.x - 1 >= 1 && maze[father.z][father.y][father.x-1] == 0 && mark[father.z][father.y][father.x-1] == 0) {
			child = father;
			child.x--;
			child.t++;

			if (child.t > time) {
				// 大于时间,就不加入了
			} else if (child.z == a && child.y == b && child.x == c && child.t <= time) {

				return child.t;// 到出口了
			} else {
				mark[child.z][child.y][child.x] = 1;
				q.push(child);
			}

		}
		// 右 x++
		if (father.x + 1 <= c && maze[father.z][father.y][father.x+1] == 0 && mark[father.z][father.y][father.x+1] == 0) {
			child = father;
			child.x++;
			child.t++;

			if (child.t > time) {
				// 大于时间,就不加入了
			} else if (child.z == a && child.y == b && child.x == c && child.t <= time) {

				return child.t;// 到出口了
			} else {
				mark[child.z][child.y][child.x] = 1;
				q.push(child);
			}

		}
		// 升 z++
		if (father.z + 1 <= a && maze[father.z+1][father.y][father.x] == 0 && mark[father.z+1][father.y][father.x] == 0) {
			child = father;
			child.z++;
			child.t++;

			if (child.t > time) {
				// 大于时间,就不加入了
			} else if (child.z == a && child.y == b && child.x == c && child.t <= time) {
				return child.t;// 到出口了
			} else {
				mark[child.z][child.y][child.x] = 1;
				q.push(child);
			}

		}
		// 降 z--
		if (father.z - 1 >= 1 && maze[father.z-1][father.y][father.x] == 0 && mark[father.z-1][father.y][father.x] == 0) {
			child = father;
			child.z--;
			child.t++;
			if (child.t > time) {
				// 大于时间,就不加入了
			} else if (child.z == a && child.y == b && child.x == c && child.t <= time) {
				return child.t;// 到出口了
			} else {
				mark[child.z][child.y][child.x] = 1;
				q.push(child);
			}

		}

	}

	return -1;
}



int main() {
	int caseNum;
	cin >> caseNum;
	for (int caseNo = 1; caseNo <= caseNum; caseNo ++) {
		cin >> a >> b >> c >> time;

		for (int i = 1; i <= a; i ++) {
			for (int j = 1; j <= b; j++) {
				for (int k = 1; k <= c; k++) {
					scanf("%d",&maze[i][j][k]);
					mark[i][j][k] = 0;
				}
			}
		}

		int res = bfs();
		cout << res << endl;

	}



}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值