• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

llwwll

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

宽搜小合集1

飞跃原野

题目大意

在一片广阔的土地上有一个鸟人,他需要从这里穿过原野回到基地。这片原野上有平地(P)、有湖泊(L)。因为鸟人可以飞,所以有的时候,他可以飞越湖泊。现在,鸟人需要用最快的时间回到基地。
假设原野是一个mxn的矩阵,有两种地形,用P和L表示。鸟人只能停留在平地上。他目前处在(1,1)这个位置,而目的地是(m,n)。他可以向上、下、左、右四个方向移动,或者飞行。每移动一格需要1个单位时间。而飞行无论飞多远,都只需要1个单位时间。飞行的途中不可以改变方向。也就是说,飞行也只能是上、下、左、右四个方向,并且一次飞行最终必须降落在平地上。当然,受到能量的限制,鸟人不能无限制地飞行,他总共最多可以飞行的距离为D。

输入

第1行是3个整数m、n和D,3个数都不超过100。
下面是一个mxn的字符矩阵,表示原野。

输出

输出一行一个整数表示最短时间。如果无法到达输出"impossible'’。

样例输入

4 4 2
PLLP
PPLP
PPPP
PLLP

样例输出

5

题意分析

显然是一个BFS题,关键点在于有飞的操作
飞的情况下可以朝一个方向一直飞或转向并且消耗体力
需要一个三维数组分别记录行,列,体力
对于时间则不需要记录(时间在BFS严格单增,第一个到(n,m)的点必然是答案

代码细节较多

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define maxn 1000010
using namespace std;
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
int n,m,k,g[110][110],vis[110][110][110],q[maxn][5],l,r;
char c; 
signed main()
{
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			cin>>c;
			if(c=='P') g[i][j]=1;
			if(c=='L') g[i][j]=2;
		} 
		
	if(!(g[n][m]==1&&g[1][1]==1)) 
	{
		cout<<"impossible"<<'\n';
		return 0;
	}
	l=0; r=1;
	q[1][1]=1,q[1][2]=1;
	q[1][3]=0,q[1][4]=k;
	while(l<r)
	{
		++l;
		int x=q[l][1];
		int y=q[l][2];
		int d=q[l][4];
		
		for(int i=0;i<4;i++)
		{
			int xx=x+dx[i];
			int yy=y+dy[i];
			
			if(g[xx][yy]==1&&!vis[xx][yy][d])
			{
				vis[xx][yy][d]=1;
				q[++r][1]=xx;
				q[r][2]=yy;
				q[r][3]=q[l][3]+1;
				q[r][4]=d;
				if(xx==n&&yy==m)
				{
					cout<<q[r][3]<<'\n';
					return 0;
				}
			}
			
			if(g[xx][yy]!=0)
			{
				for(int j=2;j<=100;j++)
				{
					xx=xx+dx[i];
					yy=yy+dy[i];
					if(j>d||g[xx][yy]==0) break;
					if(g[xx][yy]==1&&!vis[xx][yy][d-j])
					{
						vis[xx][yy][d-j]=1;
						q[++r][1]=xx;
						q[r][2]=yy;
						q[r][3]=q[l][3]+1;
						q[r][4]=d-j;
						if(xx==n&&yy==m)
						{
							cout<<q[r][3]<<'\n';
							return 0;
						}
					}
				}
			}
			
			
		}
	}
	cout<<"impossible"<<'\n';
	return 0;
}

噩梦

题目大意

给定一张 N×M 的地图,地图中有 1个男孩,1个女孩和 2个鬼。

字符 . 表示道路,字符 X 表示墙,字符 M 表示男孩的位置,字符 G 表示女孩的位置,字符 Z 表示鬼的位置。

男孩每秒可以移动 3 个单位距离,女孩每秒可以移动 1个单位距离,男孩和女孩只能朝上下左右四个方向移动。

每个鬼占据的区域每秒可以向四周扩张 2 个单位距离,并且无视墙的阻挡,也就是在第 k 秒后所有与鬼的曼哈顿距离不超过 2k 的位置都会被鬼占领。

注意: 每一秒鬼会先扩展,扩展完毕后男孩和女孩才可以移动。

求在不进入鬼的占领区的前提下,男孩和女孩能否会合,若能会合,求出最短会合时间。

输入

第一行包含整数 T,表示共有 T 组测试用例。

每组测试用例第一行包含两个整数 N 和 M,表示地图的尺寸。

接下来 NN 行每行 M 个字符,用来描绘整张地图的状况。(注意:地图中一定有且仅有 1个男孩,1个女孩和 2 个鬼)

输出

每个测试用例输出一个整数 S,表示最短会合时间。

如果无法会合则输出 −1。

每个结果占一行。

样例输入

3
5 6
XXXXXX
XZ..ZX
XXXXXX
M.G...
......
5 6
XXXXXX
XZZ..X
XXXXXX
M.....
..G...
10 10
..........
..X.......
..M.X...X.
X.........
.X..X.X.X.
.........X
..XX....X.
X....G...X
...ZX.X...
...Z..X..X

样例输出

1
1
-1

题目分析

有男孩女孩两个点同时进行BFS
对于鬼来说,每秒过后看男孩女孩与鬼的曼哈顿距离是否合法
男孩每秒走三步
将所有队列中的情况拓展
因为男女同时进行
用vis记录男女走过的路径
两者相遇输出

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define maxn 1000010
using namespace std;
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
int vis[1000][1000],Bq[maxn][3],Gq[maxn][3],gh[3][3];
char g[1000][1000];
int lb,rb,lg,rg,T;
int n,m,step,tot;
void init()
{
	memset(vis,0,sizeof vis);
	memset(Bq,0,sizeof Bq);
	memset(Gq,0,sizeof Gq);
	memset(gh,0,sizeof gh);
	lb=0,rb=1;
	lg=0,rg=1;
	step=0,tot=0;
}
bool ck(int xx,int yy,int t)
{
	if(g[xx][yy]=='X'||g[xx][yy]=='Z'||xx>n||yy>m||xx<1||yy<1) return false;
	for(int i=1;i<=2;i++)
	{
		if(abs(xx-gh[i][1])+abs(yy-gh[i][2])<=2*t) return false;
	}
	return true;
}
int solve()
{
	while(lb<rb||lg<rg)
	{
		step++;
		
		int Lg=lg;
		int Rg=rg;
		for(int bu=1;bu<=3;bu++)
		{
			int Lb=lb;
			int Rb=rb;
			for(int Lb=lb;Lb<=Rb;Lb++)
		{
			lb++;
			int x=Bq[Lb][1];
			int y=Bq[Lb][2];
			if(!ck(x,y,step)) continue;
			for(int i=0;i<4;i++)
			{
				int xx=x+dx[i];
				int yy=y+dy[i];
				if(!ck(xx,yy,step)) continue;
				if(vis[xx][yy]==1) continue;
				if(vis[xx][yy]==2) return step;
				vis[xx][yy]=1;
				Bq[++rb][1]=xx;
				Bq[rb][2]=yy;
			}
		}
		}
		
		for(int Lg=lg;Lg<=Rg;Lg++)
		{
			lg++;
			int x=Gq[Lg][1];
			int y=Gq[Lg][2];
			if(!ck(x,y,step)) continue;
			for(int bu=1;bu<=1;bu++)
			{
				for(int i=0;i<4;i++)
				{
					int xx=x+dx[i];
					int yy=y+dy[i];
					if(!ck(xx,yy,step)) continue;
					if(vis[xx][yy]==2) continue;
					if(vis[xx][yy]==1) return step;
					vis[xx][yy]=2;
					Gq[++rg][1]=xx;
					Gq[rg][2]=yy;
				}
			}
		}
	}
	return -1;
}

char c;
signed main()
{
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld%lld",&n,&m);
		init();
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++) 
			{
				cin>>c;
				g[i][j]=c;
				if(c=='Z') gh[++tot][1]=i,gh[tot][2]=j;
				if(c=='M') Bq[1][1]=i,Bq[1][2]=j;
				if(c=='G') Gq[1][1]=i,Gq[1][2]=j;
			}
		}
		cout<<solve()<<'\n';
	}
}
/*
3
5 6
XXXXXX
XZ..ZX
XXXXXX
M.G...
......
5 6
XXXXXX
XZZ..X
XXXXXX
M.....
..G...
10 10
..........
..X.......
..M.X...X.
X.........
.X..X.X.X.
.........X
..XX....X.
X....G...X
...ZX.X...
...Z..X..X
*/

posted on 2022-09-20 21:14  llwwll  阅读(203)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3