ACM算法-逃离机场

逃离机场

题目描述
小明听说机场是一个很肥的地方,所以想跳一波机场,看看到底有多肥。不过机场虽然肥,但是跳的 人也多。小明第一次跳机场,刚跳下来就到处都是枪声,小明吓得快要哭出来了,想逃离机场,emmm, 还是打野比较适合他。
现在把机场看作一个二维平面,’.’ 代表可以走的空地,’@’ 代表小明当前的位置,’x’ 代表这里是个 障碍物,’o’ 代表这里有个敌人,并且手里有枪,敌人可以攻击上下左右四个方向,小明只要走到或者一 开始就在敌人可以攻击的位置,就会死亡(机场个个都是 98K 爆头 dalao),子弹不会穿过障碍物,敌人 不会移动。小明只能往上下左右走,每走一步需要 1 秒,只要小明移动到机场的边缘再走一步就算逃离 了机场,现在小明请你帮他找一条最快逃离机场的线路,输出这个时间,如果怎么都逃不出去,输出”no zuo no die!”(不含引号)。
输入格式
多组测试数据,首先第一行一个整数 T,代表测试数据组数。1 ≤ T ≤ 100。
每组测试数据有 n, m(1 ≤ n, m ≤ 200),代表机场是一个 n × m 的方阵,接下来是一个由’.’,’@’,’x’, ’o’ 构成的 n × m 的方阵,’@’ 只有一个。
输出格式
对于每组数据输出一个数代表最快需要多少时间逃出机场,或者”no zuo no die!”。
输入样例
3
5 5
.x.x.
.x.x.

…@…
.o.o.
3 3
@…
xxx
o.x
3 3
o.o
.@.
.x.
输出样例
4
1
no zuo no die!

首先分析题目,很明显是一道搜索题目,并且是一道不确定出口的搜索题目,当小明只要走出迷宫就可以,就是说只要搜索到可以走出地图就可以,因为找的是最短路径,所以使用BFS广度搜索寻找最短路径,DFS找出口的话不一定是最短。
题目有坑不好好理解题意的话是肯定有数据是不过不去的。狙击手会四个方向开枪,意思是狙击手所在位置的四个方向直到障碍物都是不可以走的,或者说,给你的地图就是人已经在狙击手的抢线上了,就是说人上来就已经被打死了,一步都走不了。这就是最坑的地方,所以在输入数据之后就要预处理一下,然后在进行BFS搜索。把狙击手的四个枪线初始化,如果遇到障碍物子弹无法穿过,狙击手到障碍物之间的路径是不可以走的。预处理之后找到人并且人还是活着的,然后BFS找最短的出口,活着并且逃出去才可以,人死了或找不到出口都是不可以的,只能输出no zuo no die!

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int t,sx,sy,n,m,alive,out;
char mat[205][205];
int book[205][205];
int dir[][2] = {-1,0,0,1,1,0,0,-1};
struct node{
	int x,y,s;
};
void mark(int x,int y){
	book[x][y] = 1;
	for(int i=0;i<4;i++){
		int tx = x;
		int ty = y;
		while(1){
			tx = tx + dir[i][0];
			ty = ty + dir[i][1];
			if(tx < 0 || tx >= n || ty < 0 || ty >= m || mat[tx][ty] == 'x')
				break;
			if(mat[tx][ty] == '.' || mat[tx][ty] == '@')
				book[tx][ty] = 3;
		}
	}
}
int bfs(int x,int y){
	node front,tail;
	queue<node> q;
	front.x = x;
	front.y = y;
	front.s = 0;
	q.push(front);
	while(!q.empty()){
		front = q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int tx = front.x + dir[i][0];
			int ty = front.y + dir[i][1];
			if(tx < 0 || tx >=n || ty < 0 || ty >= m){
				out = 1;
				return front.s+1;
			}
			if(mat[tx][ty] == '.' && book[tx][ty] == 0){
				tail.x = tx;
				tail.y = ty;
				tail.s = front.s+1;
				book[tx][ty] = 1;
				q.push(tail);
			}
		}
	}
	return 0;
}
int main(){
	cin>>t;
	while(t--){
		alive = out = 0;
		cin>>n>>m;
		memset(book,0,sizeof book);
		for(int i=0;i<n;i++){
			cin>>mat[i];
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(mat[i][j] == 'x')
					book[i][j] = 2;
				if(mat[i][j] == 'o')
					mark(i,j);
			}
		}
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				if(mat[i][j] == '@' && book[i][j] == 0){
					sx = i;
					sy = j;
					book[i][j] = 1;
					alive = 1;
				}
//		for(int i=0;i<n;i++){
//			for(int j=0;j<m;j++)
//				cout<<book[i][j]; 
//			cout<<endl; 
//		}
		int step = bfs(sx,sy);
		if(alive && out)
			cout<<step<<endl;
		if(!alive || !out)
			cout<<"no zuo no die!"<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值