POJ 3170 Niの騎士(bfs)

説明

ベッシーはキャメロットにいて、厄介な状況に遭遇しました。彼女は、ニの騎士団によって守られている森を通り抜ける必要があります。安全に通過するために、騎士団は彼女が彼らに単一の植え込みを持ってくることを要求しました。時間は重要であり、ベッシーはできるだけ早く彼らに植え込みを見つけて持って来なければなりません。

Bessieは、X軸とY軸に平行な軸を持つ、通常の方法で配列された正方形のグリッドに分割された森の地図を持っています。マップのサイズはWx H単位です(1 <= W <= 1000; 1 <= H <= 1000)。

マップは、ベッシーがクエストを開始する場所、Niの騎士がいる単一の正方形、および土地のすべての低木地帯の場所を示しています。また、マップのどの領域をトラバースできるかを示します(沼地、崖、およびキラーウサギのために一部のグリッドブロックは通行できません)。ベッシーは低木なしではニの騎士団の広場を通り抜けることはできません。

彼女が地図に正しく従うことを確認するために、ベッシーは北、東、南、または西の4つの方向にのみ移動できます(つまり、斜めではありません)。彼女は、あるグリッドブロックから隣接するグリッドブロックへのトラバーサルを完了するのに1日かかります。

Bessieが低木を入手し、それをNiの騎士団に届けることができることが保証されています。彼女がそうするための最も速い方法を決定してください。

入力

1行目:スペースで区切られた2つの整数:WとH。

2行目…?:これらの行は、マップを1行ずつ説明しています。最初の行は、マップの最も北西の部分を示しています。最後の行は、マップの最南東部を示しています。入力の連続する整数は、西から東へのマップの列を表します。マップの説明の新しい各行は新しい入力行から始まり、各入力行には40個以下のスペースで区切られた整数が含まれます。W <= 40の場合、各入力行はマップの完全な行を表します。W> 40の場合、複数の行を使用して1つの行を記述し、最後の行を除く各行に40の整数を指定します。複数の行の要素を説明する入力行はありません。

マップを説明する整数は、このセットから取得されます
。0:ベッシーが移動できる
正方形1:ベッシーが通過できない通過できない正方形
2:ベッシーの開始位置
3:Niの騎士の
位置4:低木林の位置

出力

1行目:D、ベッシーが低木林に到達してそれをNiの騎士団に届けるのにかかる最小日数。

サンプル入力

8 4
4 1 0 0 0 0 1 0
0 0 0 1 0 1 0 0
0 2 1 1 3 0 4 0
0 0 0 4 1 1 1 0

サンプル出力

11

アイデア

まず、最小時間を見つけるには、bfsを使用して検索する必要があります。Bfsは同時にすべての場所を検索し、結果が得られたときに戻ります。これにより、最小時間を確保できます。DFSは、接続されているすべての接続を一度に検索します。時間を比較するのは簡単ではありません。私は長い間これをしていません。最初は、始点から直接終点を検索し、茂みを通過するときにマークを付けます。マーキングを通過した後、終点で終了しますが、最尤法です。その後、各ブッシュはそれぞれbfsの開始点と終了点として採用され、2つの最小値がTLEとして採用されます。次に、始点と終点からそれぞれ茂みの検索を開始しますが、グラフ全体を終了せずにトラバースして、各茂みの時間を記録し、最後に2つを合計して最小値を取ります。詳細は注記を参照してください

コード

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int xx[]={
    
    0,0,1,-1};					//方向 
const int yy[]={
    
    1,-1,0,0};
struct state
{
    
    
	int x,y,t;								//位置 时间 
};
queue<state> q;
int map[1005][1005];
int t[1005][1005][2];						//分别记录起点和终点到灌木的时间 
int vis[1005][1005];						//标记走过的位置  因为要最小的时间,走过的顺序是按照时间的,后面的时间肯定比前面大且没有其他条件影响 
int x0,y0,w,h,x,y;							//起点 终点 

inline int read()							//快读 
{
    
    
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}

void bfs(int sx,int sy,int p)				//起点位置  p是记录此次bfs的是起点还是终点 
{
    
    
	while(q.size())
		q.pop();
	state tmp;
	tmp.x=sx;
	tmp.y=sy;
	tmp.t=0;								//起点 
	q.push(tmp);
	while(q.size())
	{
    
    
		tmp=q.front();
		q.pop();
		for(int i=0;i<4;i++)				//向四周走 
		{
    
    
			int dx=tmp.x+xx[i],dy=tmp.y+yy[i];
			if(dx>h||dy>w||dx<1||dy<1||vis[dx][dy]||map[dx][dy]==1)
				continue;					//条件判断 超界 走过 死路 
			vis[dx][dy]=1;					//标记 
			state st;
			st.x=dx;
			st.y=dy;
			st.t=tmp.t+1;
			if(map[dx][dy]==4)
				t[dx][dy][p]=st.t;			//灌木丛记录时间 
			q.push(st);						//加入队列,搜索其四周 
		}
	}
}

int main()
{
    
    
	cin>>w>>h;
	queue<state>bush;
	for(int i=1;i<=h;i++)
		for(int j=1;j<=w;j++)
		{
    
    
			map[i][j]=read();
			if(map[i][j]==2)
			{
    
    
				x0=i;
				y0=j;
			}
			if(map[i][j]==3)
			{
    
    
				x=i;
				y=j;
			}
		}
	int ans=1e8;
	bfs(x0,y0,0);							//从起点bfs灌木 
	memset(vis,0,sizeof(vis));				//标记清零 
	bfs(x,y,1);								//从终点bfs灌木 
	for(int i=1;i<=h;i++)
		for(int j=1;j<=w;j++)
			if(map[i][j]==4&&t[i][j][0]&&t[i][j][1])	//注意!!!可能有的灌木无法到达 
				ans=min(t[i][j][0]+t[i][j][1],ans);
	cout<<ans;
	return 0;
}

おすすめ

転載: blog.csdn.net/m0_54621932/article/details/113959415