牛客小白月赛61_C-小喵觅食题解

题目描述:

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网

现实世界可以抽象为一张 n×mn \times mn×m 大小的二维地图。PLMM 的初始坐标在 (x1,y1)(x_1,y_1)(x1​,y1​),活动范围 r1r_1r1​ 表示 PLMM 只会移动到坐标为 (x,y)(x,y)(x,y) 的位置 (0≤∣x−x1∣+∣y−y1∣≤r1)(0 \leq |x-x_1|+|y-y_1| \leq r_1)(0≤∣x−x1​∣+∣y−y1​∣≤r1​)。小喵的初始坐标在 (x2,y2)(x_2,y_2)(x2​,y2​),鼻子灵敏度 r2r_2r2​ 表示小喵只能闻到坐标为 (x,y)(x,y)(x,y) 的位置的小鱼干 (0≤∣x−x2∣+∣y−y2∣≤r2)(0 \leq |x-x_2|+|y-y_2| \leq r_2)(0≤∣x−x2​∣+∣y−y2​∣≤r2​)。此外,地图中存在若干障碍物使得 PLMM 和小喵无法通过。

若 PLMM 或小喵当前的坐标为 (x,y)(x,y)(x,y),则下一步可以移动到 (x−1,y), (x,y−1), (x+1,y)(x-1,y),\,(x,y-1),\,(x+1,y)(x−1,y),(x,y−1),(x+1,y) 或 (x,y+1)(x,y+1)(x,y+1) 坐标的位置。起初,小喵保持原地不动,但当闻到小鱼干的气味时便会朝 PLMM 的位置跑去。在小喵开始移动的同时,PLMM 会担心吓跑小喵从而保持原地不动。需要注意的是,鼻子灵敏度 r2r_2r2​ 只能决定小喵能否闻到小鱼干的气味,对小喵的移动范围没有限制。小喵闻到小鱼干气味后便会锁定 PLMM 的位置,即使之后闻不到小鱼干的位置,也会继续朝 PLMM 的位置移动。

若小喵可以吃到小鱼干,PLMM 想知道自己与小喵移动的距离和最小值。 

思路: 

本题是两个BFS,算出人到每个点的距离和猫到每个点的距离相加后求最小值。人是有活动范围而猫没有活动范围,这里在BFS的时候可以看作猫的活动范围无限大。

这里先放最核心的bfs代码,不理解bfs的可以移步至DFS和BFS理解+模板+例题

char s[1005][1005];/*储存地图信息*/
int n,m,r1/*人活动范围*/,r2/*猫嗅觉范围*/; 
int dx[]={-1,1,0,0};//用于遍历人/猫上下左右移动的情况
int dy[]={0,0,-1,1};
int dis[2][1005][1005];//储存到起点的距离,0为人1为猫 
int mx,my;/*猫的坐标*/
void bfs(int k/*0为人1为猫*/,int x/*起始横坐标*/,int y/*起始纵坐标*/,int r/*活动范围*/){
	queue<pair<int,int>> q;
	pair<int,int> t;
	dis[k][x][y]=0;
	q.push({x,y});
	while(!q.empty()){
		t=q.front();
		q.pop();
		int nx=t.first;
		int ny=t.second;
		for(int i=0;i<4;i++){
			int nnx=nx+dx[i];
			int nny=ny+dy[i];
			if(nnx>0 && nnx<=n && nny>0 &&nny<=m&&//目标移动点在范围内 
			   s[nnx][nny]!='*' && dis[k][nnx][nny]==0x3f3f3f3f &&//不是阻挡物而且是没去过的点 
			   abs(nnx-x)+abs(nny-y)<=r)//距离起始点距离不超过r 
			{
			   	q.push({nnx,nny});
			   	dis[k][nnx][nny]=dis[k][nx][ny]+1;
			}
		}
	}
} 

 因为要计算每个点到人/猫的最短距离,采用bfs可以确保第一次读到一个点的时候的值就是最小值。计算人时bfs参数的r采用r1,猫则采用0x3f3f3f3f(int的最大值)。

main函数中就是简单的读取和枚举判断点是否符合条件

完整AC代码:

#include<bits/stdc++.h>
using namespace std;
char s[1005][1005];
int n,m,r1/*人活动范围*/,r2/*猫嗅觉范围*/; 
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int dis[2][1005][1005];//储存到起点的距离,0为人1为猫 
int mx,my;/*猫的坐标*/
void bfs(int k/*0为人1为猫*/,int x/*起始横坐标*/,int y/*起始纵坐标*/,int r/*活动范围*/){
	queue<pair<int,int>> q;
	pair<int,int> t;
	dis[k][x][y]=0;
	q.push({x,y});
	while(!q.empty()){
		t=q.front();
		q.pop();
		int nx=t.first;
		int ny=t.second;
		for(int i=0;i<4;i++){
			int nnx=nx+dx[i];
			int nny=ny+dy[i];
			if(nnx>0 && nnx<=n && nny>0 &&nny<=m&&//目标移动点在范围内 
			   s[nnx][nny]!='*' && dis[k][nnx][nny]==0x3f3f3f3f &&//不是阻挡物而且是没去过的点 
			   abs(nnx-x)+abs(nny-y)<=r)//距离起始点距离不超过r 
			{
			   	q.push({nnx,nny});
			   	dis[k][nnx][nny]=dis[k][nx][ny]+1;
			}
		}
	}
} 
int main(){
	cin>>n>>m>>r1>>r2;
	memset(dis,0x3f3f3f3f,sizeof(dis));
	for(int i=1;i<=n;i++){//读取地图信息
		scanf("%s",s[i]+1);//s[i]是字符串数组s[i]的首地址,s[i]+1就意味着从s[i][1]开始存 
	}
	for(int i=1;i<=n;i++){ 
		for(int j=1;j<=m;j++){
			if(s[i][j]=='P') bfs(0,i,j,r1);/*广搜人能到达地方并储存到那里的距离*/
			else if(s[i][j]=='M'){
				bfs(1,i,j,0x3f3f3f3f);/*广搜猫能到的地方并储存到那里的距离*/
				mx=i;/*储存猫的坐标*/
				my=j;
			}	 
		}
	}
	int minn=0x3f3f3f3f;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(abs(i-mx)+abs(j-my)<=r2){//该点在猫嗅觉范围内
				minn=min(minn,dis[0][i][j]+dis[1][i][j]);//因为到不了的地方默认int的上限值所以自动排除 
			}
		}
	}
	if(minn==0x3f3f3f3f) cout<<"-1"<<'\n';//如果minn不变说明没有符合条件的点输出-1 
	else cout<<minn<<'\n';
	return 0; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值