AtCoder 184 E

184 E

题目地址
虽然是E题,但其实就是一个标准的bfs
不用走重复路线,因为bfs总是选择最优,走重复毫无意义
具体细节,在代码里标注了。

#include <bits/stdc++.h>
using namespace std;
#define please return
#define AC 0
struct node
{
	int x;
	int y;
	int step;//步数 
};

node make_node(int d,int e,int f)
{
	node ret;
	ret.x=d;
	ret.y=e;
	ret.step=f;
	return ret;
}

int dx[4]={0,0,-1,1};//位移增量 
int dy[4]={1,-1,0,0};

int h,w,ans=4000000;
int sx,sy,ex,ey;//起始点的横纵坐标 

int a[2005][2005];
bool vis[2005][2005];

vector<pair<int,int> > v[35];
//对于每一个相同小写字母(可以穿梭)我们记录下他们的下标,方便查找
// 举个例子,比如说v[1]里的每个向量就是记录每个a的下标,pair量。
//v[2]里记录每个b的下标,以此类推。 
queue<node> q;

inline bool check(int i,int j)//判断是否合法,太长了,所以拿出来了... 
{
	if(i>=1&&i<=h && j>=1&&j<=w &&!vis[i][j] && a[i][j]!=-1) return 1;
	 else return 0;
}

int main()
{
	cin>>h>>w;
	for(int i=1;i<=h;i++)//重新构建矩阵,方便进行搜索 
	 for(int j=1;j<=w;j++)
	 {
	 	char now;
	 	cin>>now;
	 	
	 	if(now=='S')
	 	{
	 		sx=i;
	 		sy=j;
		 }
		else if(now=='G')
		{
			ex=i;
			ey=j;
		}
		else if(now=='#') a[i][j]=-1;
		else if(now=='.') a[i][j]=0;
		else if(now>='a'&&now<='z')
		{
			a[i][j]=now-'a'+1;
			v[a[i][j]].push_back(make_pair(i,j));
		}
	 }
	
	q.push(make_node(sx,sy,0));
	vis[sx][sy]=true;
	
	while(!q.empty())
	{
		node fr=q.front();
		int xx=fr.x,yy=fr.y;
		q.pop();
		
		if(xx==ex&&yy==ey) ans=min(ans,fr.step);
		
		for(int i=0;i<4;i++)
		{
			int nx=xx+dx[i];
			int ny=yy+dy[i];
			
			if(check(nx,ny))
			{
				q.push(make_node(nx,ny,fr.step+1));
				vis[nx][ny]=true;
			}
		}
		if(a[xx][yy])
		{
			for(int j=0;j<v[a[xx][yy]].size();j++)
			{
				int x1=v[a[xx][yy]][j].first;
				int y1=v[a[xx][yy]][j].second;
				if(!vis[x1][y1])
				{
					q.push(make_node(x1,y1,fr.step+1));
					vis[x1][y1]=true;
				}
			}
			v[a[xx][yy]].clear();
		}
	}
	if(ans==4000000) cout<<"-1";
	 else cout<<ans;
	 please AC;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值