复试训练——搜索——广度优先搜索(BFS)

题目1456:胜利大逃亡

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:3091

解决:1111

题目描述:

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

输入:

输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙。

输出:

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

样例输入:

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

样例输出:

11

代码:

#include <stdio.h>
#include <queue>
using namespace std;
bool mark[50][50][50];
int maze [50][50][50];
struct N{
	int x,y,z;
	int t;
};
queue<N> Q;
int go[][3]={
	1,0,0,
	-1,0,0,
	0,1,0,
	0,-1,0,
	0,0,1,
	0,0,-1
};
int BFS(int a,int b,int c){
	while(Q.empty()==false){
		N now=Q.front();
		Q.pop();
		int i;
		for(i=0;i<6;i++){
			int nx=now.x+go[i][0];
			int ny=now.y+go[i][1];
			int nz=now.z+go[i][2];
			if(nx<0||nx>=a||ny<0||ny>=b||nz<0||nz>=c) continue;
			if(maze[nx][ny][nz]==1) continue;
			if(mark[nx][ny][nz]==true) continue;
			N tmp;

			tmp.x=nx;
			tmp.y=ny;
			tmp.z=nz;
			tmp.t=now.t+1;
			Q.push(tmp);
			mark[nx][ny][nz]=true;
			if(nx==a-1&&ny==b-1&&nz==c-1) return tmp.t;
		}
	}
	return -1;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
	int a,b,c,t;
	scanf("%d%d%d%d",&a,&b,&c,&t);
	int i;
	for(i=0;i<a;i++){
		int j;
		for(j=0;j<b;j++){
			int k;
			for(k=0;k<c;k++){
				scanf("%d",&maze[i][j][k]);
				mark[i][j][k]=false;
			}
		}
	}
	while(Q.empty()==false) Q.pop();
	mark[0][0][0]=true;
	N tmp;
	tmp.t=tmp.x=tmp.y=tmp.z=0;
	Q.push(tmp);
	int rec=BFS(a,b,c);
	if(rec<=t) printf("%d\n",rec);
	else printf("-1\n");
	}
	return 0;
}

题目1457:非常可乐

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:1262

解决:595

题目描述:

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升(正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

输入:

三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。

输出:

如果能平分的话请输出最少要倒的次数,否则输出"NO"。

样例输入:

7 4 3
4 1 3
0 0 0

样例输出:

NO
3

代码:

#include <stdio.h>
#include <queue>
using namespace std;
struct N{
	int a,b,c;
	int t;
};
queue<N> Q;
bool mark[101][101][101];
void AtoB(int &a,int sa,int &b,int sb){
	if(sb-b>=a){
		b+=a;
		a=0;
	}else{
		a-=sb-b;
		b=sb;
	}
}
int BFS(int s,int n,int m){
	while(Q.empty()==false){
		N now=Q.front();
		Q.pop();
		int a,b,c;
		a=now.a;
		b=now.b;
		c=now.c;
		AtoB(a,s,b,n);
		if(mark[a][b][c]==false){
			mark[a][b][c]=true;
			N tmp;
			tmp.a=a;
			tmp.b=b;
			tmp.c=c;
			tmp.t=now.t+1;
			if(a==s/2&&b==s/2) return tmp.t;
			if(c==s/2&&b==s/2) return tmp.t;
			if(a==s/2&&c==s/2) return tmp.t;
			Q.push(tmp);
		}
		a=now.a;
		b=now.b;
		c=now.c;
		AtoB(b,n,a,s);
		if(mark[a][b][c]==false){
			mark[a][b][c]=true;
			N tmp;
			tmp.a=a;
			tmp.b=b;
			tmp.c=c;
			tmp.t=now.t+1;
			if(a==s/2&&b==s/2) return tmp.t;
			if(c==s/2&&b==s/2) return tmp.t;
			if(a==s/2&&c==s/2) return tmp.t;
			Q.push(tmp);
		}
		a=now.a;
		b=now.b;
		c=now.c;
		AtoB(a,s,c,m);
		if(mark[a][b][c]==false){
			mark[a][b][c]=true;
			N tmp;
			tmp.a=a;
			tmp.b=b;
			tmp.c=c;
			tmp.t=now.t+1;
			if(a==s/2&&b==s/2) return tmp.t;
			if(c==s/2&&b==s/2) return tmp.t;
			if(a==s/2&&c==s/2) return tmp.t;
			Q.push(tmp);
		}
		a=now.a;
		b=now.b;
		c=now.c;
		AtoB(c,m,a,s);
		if(mark[a][b][c]==false){
			mark[a][b][c]=true;
			N tmp;
			tmp.a=a;
			tmp.b=b;
			tmp.c=c;
			tmp.t=now.t+1;
			if(a==s/2&&b==s/2) return tmp.t;
			if(c==s/2&&b==s/2) return tmp.t;
			if(a==s/2&&c==s/2) return tmp.t;
			Q.push(tmp);
		}
		a=now.a;
		b=now.b;
		c=now.c;
		AtoB(b,n,c,m);
		if(mark[a][b][c]==false){
			mark[a][b][c]=true;
			N tmp;
			tmp.a=a;
			tmp.b=b;
			tmp.c=c;
			tmp.t=now.t+1;
			if(a==s/2&&b==s/2) return tmp.t;
			if(c==s/2&&b==s/2) return tmp.t;
			if(a==s/2&&c==s/2) return tmp.t;
			Q.push(tmp);
		}
		a=now.a;
		b=now.b;
		c=now.c;
		AtoB(c,m,b,n);
		if(mark[a][b][c]==false){
			mark[a][b][c]=true;
			N tmp;
			tmp.a=a;
			tmp.b=b;
			tmp.c=c;
			tmp.t=now.t+1;
			if(a==s/2&&b==s/2) return tmp.t;
			if(c==s/2&&b==s/2) return tmp.t;
			if(a==s/2&&c==s/2) return tmp.t;
			Q.push(tmp);
		}

	}
	return -1;
}
int main(){

	int s,n,m;
	while(scanf("%d%d%d",&s,&n,&m)!=EOF){
		if(s==0) break;
		if(s%2==1){
		puts("NO");
		continue;
		}
		int i;
		for(i=0;i<=s;i++){
			int j;
			for(j=0;j<=n;j++){
				int k;
				for(k=0;k<=m;k++){
					mark[i][j][k]=false;
				}
			}
		}
		N tmp;
		tmp.a=s;
		tmp.b=0;
		tmp.c=0;
		tmp.t=0;
		while(Q.empty()==false) Q.pop();
		Q.push(tmp);
		mark[s][0][0]=true;
		int rec=BFS(s,n,m);
		if(rec==-1)
			puts("NO");
		else 
			printf("%d\n",rec);
	}
	return 0;
}

 

转载于:https://my.oschina.net/u/1996306/blog/833290

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值