宽搜 bfs 求解地图中初始位置到目的位置最短的路径 两道题

简介: 宽搜 bfs 求解地图中初始位置到目的位置最短的路径 两道题

第一题:



解题大致过程:


首先要提前准备的四个数组

1.1 第一个是用来存放地图的

1.2 第二个用来存放保存记录,

1.3 第三个用来进行队列的

1.4 第四个是存放上下左右方向的

就一个队列循环结束即可,不需要像深搜一样

在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


相关文章
|
23天前
|
算法 测试技术 C#
【解析几何】 【多源路径】 【贪心】1520 最多的不重叠子字符串
【解析几何】 【多源路径】 【贪心】1520 最多的不重叠子字符串
|
21天前
|
机器学习/深度学习
动态规划|【路径问题】|931.下降路径最小和
动态规划|【路径问题】|931.下降路径最小和
【图论】【深度优先搜索】【换根法】2858. 可以到达每一个节点的最少边反转次数
【图论】【深度优先搜索】【换根法】2858. 可以到达每一个节点的最少边反转次数
|
4月前
|
算法 Java C++
数据结构与算法面试题:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。(提示:使用动态规划或者中心扩散)
数据结构与算法面试题:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。(提示:使用动态规划或者中心扩散)
44 0
|
4月前
leetcode-6110:网格图中递增路径的数目
leetcode-6110:网格图中递增路径的数目
22 1
|
4月前
leetcode-1964:找出到每个位置为止最长的有效障碍赛跑路线
leetcode-1964:找出到每个位置为止最长的有效障碍赛跑路线
15 0
|
5月前
|
机器学习/深度学习 算法 C++
【算法 | 实验6-1】n*n的网格,从左上角开始到右下角结束遍历所有的方块仅一次,总共有多少种不同的遍历路径
前言 思路介绍中省略了关于如何进行回溯搜索的细节,而主要讨论回溯中所使用的剪枝策略。
63 0
|
5月前
|
算法 测试技术 C#
C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
|
6月前
|
人工智能 算法
代码随想录算法训练营第三十五天 | LeetCode 435. 无重叠区间、763. 划分字母区间、56. 合并区间
代码随想录算法训练营第三十五天 | LeetCode 435. 无重叠区间、763. 划分字母区间、56. 合并区间
41 0
|
9月前
|
算法 C语言 C++
【模拟】特别数的和、移动距离、连号区间、错误票据思路详解及代码实现
取出最后一位,然后将n除去最后一位,将刚刚取出的进行判定。
48 0