寬搜 bfs 求解地圖中初始位置到目的位置最短的路徑 兩道題

第一題
在這裏插入圖片描述
解題大致過程

  1. 首先要提前準備的四個數組
    1.1 第一個是用來存放地圖的
    1.2 第二個用來存放保存記錄,
    1.3 第三個用來進行隊列的
    1.4 第四個是存放上下左右方向的
  2. 就一個隊列循環結束即可,不需要像深搜一樣
  3. 在while 隊列中
    3.1 隊列過程中每到一個位置時會進行上下左右進行列舉,這裏用一個for循環,
    3.2 在循環中開始獲取下一個位置,獲取到之後首先判斷是否當前位置是超過這張地圖的範圍,是的話 continue 直接換位置
    3.3 判斷這個點是否爲障礙物,或者是否曾經訪問過這個點,不是的話增加到隊列中尾部加一
    3.4 判斷這個點是否是終點,是的話用一個flag=1來表示已經找到了,直接退出for循環列舉方向
    3.5 結束for在while中判斷是否得到flag爲1的信號及時退出,沒有的話說明這個點已經所有位置都訪問過,進行隊列中下一個位置

輸入條件:
5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3

代碼

#include <stdio.h>
struct node{
	int x; //橫座標
	int y; //縱座標
	int f;  //父親在隊列中的編號
	int s;  //步數 
}; 

int main()
{
	struct node que[2501];  //因爲地圖不會超過50*50的,也因此隊列擴展不會超過2500個
	int a[51][51]={0},book[51][51]={0};
	int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
	int head,tail,n,m,i,j,startx,starty,p,q,flag,tx,ty,k;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	scanf("%d%d%d%d",&startx,&starty,&p,&q);
	
	//進行隊列初始化
	head = 1;
	tail = 1;
	//往隊列中插入迷宮入口座標
	que[tail].x = startx;
	que[tail].y = starty;
	que[tail].f = 0;
	que[tail].s = 0;
	tail++;
	book[startx][starty]=1;
	
	flag = 0; // 用來標記是否達到目標點,0表示暫時還沒有到達
	//當隊列不爲空的時候循環
	while(head<tail)
	{
		for(k=0;k<=3;k++)
		{
			//計算下一個點的座標 
			tx = que[head].x+next[k][0];
			ty = que[head].y+next[k][1];
			//判斷是否越界
			if(tx<1||tx>n||ty<1||ty>m){
				continue;
			} 
			//判斷是否是障礙物或者已經在路徑中
			if(a[tx][ty]==0&&book[tx][ty]==0)
			{
				//把這個點標記爲已經走過
				//注意寬搜每個點只入隊一次,所以和深搜不同,不需要將book還原
				book[tx][ty]=1;
				//插入新的點到隊列中
				que[tail].x = tx;
				que[tail].y = ty;
				que[tail].f = head;
				que[tail].s = que[head].s+1;
				tail++;
			}
			//判斷到目標點了,停止擴展,任務結束,退出循環
			if(tx==p&&ty==q)
			{
				flag=1;
				break;
			} 
		}
		if(flag==1)
			break;
		head++;    //第一個擴展點結束後才進行增1 
	} 
	//指向末尾最後一個的點數 
	printf("%d",que[tail-1].s); 
	return 0;
} 

運行結果爲:7

————————————————————————————————————————

第二題 找到合理的位置求出能夠消滅最多的敵人

在這裏插入圖片描述
必須在空曠的位置走

輸入條件
13 13 3 3
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#…#…G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G…G…#
#G#.#G###.#G#
#…G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############

代碼

#include <stdio.h>
struct node{
	int x;   //橫座標 
	int y;   //縱座標 
};
char a[20][21];   //定義地圖

//得到對應的點能炸敵人的和 
int getnum(int i,int j)
{
	int sum,x,y;
	sum=0;  //求消滅的敵人
	x=i,y=j;
	while(a[x][y]!='#')  //向上統計 
	{
		if(a[x][y]=='G')
			sum++;
		x++;
	} 
	
	x=i,y=j;
	while(a[x][y]!='#')  //向下統計 
	{
		if(a[x][y]=='G')
			sum++;
		x--;
	} 
	
	x=i,y=j;
	while(a[x][y]!='#')  //向右統計 
	{
		if(a[x][y]=='G')
			sum++;
		y++;
	} 
	
	x=i,y=j;
	while(a[x][y]!='#')  //向左統計 
	{
		if(a[x][y]=='G')
			sum++;
		y--;
	} 
	
	return sum; 
} 
int main()
{
	struct node que[401];
	int head,tail;   //定義頭尾
	int book[20][20]={0};
	int next[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
	int i,j,n,m,startx,starty,mx,my,tx,ty,sum=0,max;
	scanf("%d%d%d%d",&n,&m,&startx,&starty);  //輸入行列
	for(i=0;i<n;i++)
		scanf("%s",a[i]); 
		
	//隊列初始化
	head=1;
	tail=1;
	//往隊列中插入小人的起始座標
	que[tail].x = startx;
	que[tail].y = starty;
	tail++;
	book[startx][starty]=1;
	max = getnum(startx,starty);
	mx = startx;
	my = starty;
	//當隊列不爲空的時候循環
	while(head<tail)
	{
		//枚舉四個方向
		for(i=0;i<4;i++)
		{
			//嘗試走的下一個點座標 
			tx=que[head].x+next[i][0];
			ty=que[head].y+next[i][1];
			
			//判斷是否越界
			if(tx<0||tx>n-1||ty<0||ty>m-1){
				continue;
			} 
			if(a[tx][ty]=='.'&&book[tx][ty]==0){
				book[tx][ty] = 1;
				//插入新的擴展點到隊列中
				que[tail].x = tx;
				que[tail].y = ty;
				tail++;
				
				//統計當前消滅敵人總數
				sum = getnum(tx,ty);
				if(sum>max){
					max = sum;
					mx = tx;  //記錄點 
					my = ty;
				}//if 
			}//if
		}//for
		head++;  //進行擴展 
	}//while 
	 printf("炸彈放在(%d,%d)中消滅最多敵人數:%d",mx,my,max); 
	return 0;
} 

輸出結果爲:炸彈放在(7,11)中消滅最多敵人數:10

                             								可以加羣一起討論891507813
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章