1. 程式人生 > >[openjudge-搜尋]廣度優先搜尋之鳴人和佐助

[openjudge-搜尋]廣度優先搜尋之鳴人和佐助

題目描述

描述

佐助被大蛇丸誘騙走了,鳴人在多少時間內能追上他呢?已知一張地圖(以二維矩陣的形式表示)以及佐助和鳴人的位置。地圖上的每個位置都可以走到,只不過有些位置上有大蛇丸的手下,需要先打敗大蛇丸的手下才能到這些位置。鳴人有一定數量的查克拉,每一個單位的查克拉可以打敗一個大蛇丸的手下。假設鳴人可以往上下左右四個方向移動,每移動一個距離需要花費1個單位時間,打敗大蛇丸的手下不需要時間。如果鳴人查克拉消耗完了,則只可以走到沒有大蛇丸手下的位置,不可以再移動到有大蛇丸手下的位置。佐助在此期間不移動,大蛇丸的手下也不移動。請問,鳴人要追上佐助最少需要花費多少時間?

輸入

輸入的第一行包含三個整數:MN

T。代表MN列的地圖和鳴人初始的查克拉數量T0 < M,N < 2000 T < 10

後面是MN列的地圖,其中@代表鳴人,+代表佐助。*代表通路,#代表大蛇丸的手下。

輸出

輸出包含一個整數R,代表鳴人追上佐助最少需要花費的時間。如果鳴人無法追上佐助,則輸出-1

樣例輸入

樣例輸入1

4 4 1

#@##

**##

###+

****

樣例輸入2

4 4 2

#@##

**##

###+

****

樣例輸出

樣例輸出1

6

樣例輸出2

4

題目分析

這是一升級版的BFS題,比起迷宮來看,多了“穿牆”這一新技能。解決這道題的關鍵要素主要在bool陣列上。需要定義一個三維陣列,分別要區分開行,列與所剩查克拉數量。因此佇列也需要三個,其他部分與迷宮大致相同。

BFS條件判斷:不超出邊界,查克拉不小於零,方法不重複。

BFS退出條件:到達終點

程式碼實現

#include<iostream>
#include<cstring>
using namespace std;
int head=0,tail=1,q,nextx,nexty,nextck,n,m,startx,starty,overx,overy;
int a[100005],b[100005],ck[100005],pre[100005],x[4]={1,0,-1,0},y[4]={0,1,0,-1},c,CKL;
bool mark[205][205][15];
char map[205][205];
void print(int d)
{
	if(pre[d]!=0)print(pre[d]);
	//printf("(%d,%d,%d)\n",a[d],b[d],ck[d]);
	c++;
}
bool chek(int qx,int qy,int qz)
{
	if(qx<=n-1&&qy<=m-1&&qx>=0&&qy>=0&&qz>=0)return 1;
	return 0;
}
void bfs()
{
	memset(b,0,sizeof(b));
	memset(a,0,sizeof(a));
	memset(ck,0,sizeof(ck));
	memset(mark,0,sizeof(mark));
	a[1]=startx;
	b[1]=starty;
	ck[1]=CKL;
	mark[startx][starty][CKL]=1;
	pre[1]=0;
	head=0;tail=1;
	while(head!=tail)
		{
			head++;
			for(int i=0;i<=3;i++)
			{
				nextx=a[head]+x[i];
				nexty=b[head]+y[i];	
				nextck=ck[head];
				if(map[nextx][nexty]=='#')nextck--;
				if(!mark[nextx][nexty][nextck]&&chek(nextx,nexty,nextck))
				{
					tail++;
					a[tail]=nextx;
					b[tail]=nexty;
					ck[tail]=nextck;
					pre[tail]=head;
					mark[nextx][nexty][nextck]=1; 
					if(a[tail]==overx&&b[tail]==overy)
					{
						print(tail);
						printf("%d\n",c-1);
						return ;
					}
				}
			}
		}
	printf("-1\n");
}
int main()
{
	scanf("%d%d%d",&n,&m,&CKL);
	for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='@'){startx=i;starty=j;map[i][j]='.';}
				if(map[i][j]=='+'){overx=i;overy=j;map[i][j]='.';}
			}
	bfs();
}

後記

這是本人第一次寫部落格,肯定有遺漏或者更好的方法,請大家多多指教^_^

Writing by Panda Hu 2017.5.20