BFS+优先队列 P7775 [COCI 2009-2010 #2] VUK

 题目

 思路

这道题有一句话特别难懂:帮忙找出这样一条从VJ的路径,使得 Vjekoslav 在途中离它最近的树的距离的最小值最大

最近 最小值 最大 我直接晕了

分析一下:

  1. 最近:t棵树中最近的那棵tree。
  2. 最小值:离tree最近的那个点p和tree的距离。
  3. 最大:使p和tree的距离最大。

意思就是,选择一条v到j的路径,使路上的每个点都和树离得越远越好。

代码

注释多多;数据结构和思路都写得比较详细。

#include<bits/stdc++.h> 
using namespace std;
char g[505][505];
int mhd[505][505],vis[505][505];
int n,m;
//用于存储点信息,更新曼哈顿距离 
struct node{
	int x,y,d;
};
struct wolf{
	int x,y,d; 
	//降序,为了使狼到树的距离越远越好
	bool operator < (const wolf w)const
	{
		return w.d>d; 
	}
}start,endj; 
//队列q:用于计算所有定点到最近的树的曼哈顿距离 
queue <node> q;
//优先队列q:根据d降序入队,为了走离树更远的路径 
priority_queue <wolf> p;
int xd[4]={0,0,1,-1};
int yd[4]={1,-1,0,0};

//预处理曼哈顿 距离 打表 
void bfs1()
{
	while(!q.empty())
	{
		node cur=q.front();
		q.pop();
		//四个方向都走一格,如果没走过就 
		for(int i=0;i<4;i++)
		{
			int xn=cur.x+xd[i];
			int yn=cur.y+yd[i];
			//注意一下x是行,y是列 
			//如果点在图内且未被访问,更新其曼哈顿距离 
			//因为是从树开始扩散开,所以可以保证是层次遍历,越早遍历到曼哈顿距离最短 
			if(0<=xn&&xn<n&&0<=yn&&yn<m&&!vis[xn][yn])
			{
				mhd[xn][yn]=cur.d+1;
				//cout<<"x="<<xn<<"y="<<yn<<"mhd:"<<mhd[xn][yn]<<endl;
				q.push(node{xn,yn,mhd[xn][yn]});
				vis[xn][yn]=1;
			}
		}
	}
}

//起始点先入队,然后bfs
//由于bfs是层次遍历,因此到终点的路线是较短的
//优先队列的性质告诉我们每次队首都是队列离树最远的节点 
int bfs2()
{
	memset(vis,0,sizeof(vis));
	start.d=mhd[start.x][start.y];
	p.push(start);
	vis[start.x][start.y]=1;
	while(!p.empty())
	{
		wolf cur=p.top();
		p.pop();
		//cout<<"pop:x="<<cur.x<<"y:"<<cur.y<<"d:"<<cur.d<<endl;
		if(cur.x==endj.x&&cur.y==endj.y)
		{
			//cout<<"终点到!";
			return cur.d;
			break;
		}
		for(int i=0;i<4;i++)
		{
			int xn=cur.x+xd[i];
			int yn=cur.y+yd[i];
			// 
			if(0<=xn&&xn<n&&0<=yn&&yn<m&&!vis[xn][yn])
			{
				//cout<<"push:x="<<xn<<"y="<<yn<<"d:"<<min(mhd[xn][yn],cur.d)<<endl;
				p.push(wolf{xn,yn,min(mhd[xn][yn],cur.d)});
				vis[xn][yn]=1;
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>g[i][j];
			
			if(g[i][j]=='+')
			{
				node a;
				a.x=i;a.y=j;a.d=0;
				q.push(a);
				vis[i][j]=1;
				//树上的曼哈顿距离是0; 
				mhd[i][j]=0;
			 } 
			 else if(g[i][j]=='V')
			 {
			 	start.x=i;
			 	start.y=j;
			 }
			 else if(g[i][j]=='J')
			 {
			 	endj.x=i;
			 	endj.y=j;
			 }
		}
	}
	//bfs可以遍历连通图 
	bfs1();
	cout<<bfs2();
}

猜你喜欢

转载自blog.csdn.net/LarsGyonX/article/details/124618449