当前位置: 首页 > article >正文

算法-深度优先搜索

在图上寻找路径

在图上如何寻找从1到8的路径? 一种策略:只要能发现没走过的点, 就走到它。有多个点可走就随便挑一 个,如果无路可走就回退,再看有没有没走过的点可走。

运气最好:1->2->4->8 2

运气稍差:1->2->4->5->6->8

运气坏: 1->3->7->9=>7->A=>7=>3->5->6->8 (双线箭头表示回退)

不连通的图,无法从节点1走到节点8。完整的尝试过程可能如下: 1->2->4->3->7=>3=>4=>2 >9=>2=>1。

深度优先搜索(Depth-First-Search)

从起点出发,走过的点要做标记,发现有没走过的点,就随意挑一个往前走,走不 了就回退,此种路径搜索策略就称为“深度优先搜索”,简称“深搜”。 其实称为“远度优先搜索”更容易理解些。因为这种策略能往前走一步就往前走一 步,总是试图走得更远。所谓远近(或深度),就是以距离起点的步数来衡量的。

城堡问题

计算城堡一共有多少房间, 最大的房间有多大。城堡 被分割成m×n(m≤50, n≤50)个方块,每个方块可 以有0~4面墙。

输入

  •  程序从标准输入设备读入数据。
  •  第一行是两个整数,分别是南北向、东西向的方块数。
  •  在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数 字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南 墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两 次,方块(1,1)的南墙同时也是方块(2,1)的北墙。
  •  输入的数据保证城堡至少有两个房间。

 输出

  •  城堡的房间数、城堡中最大房间所包括的方块数。
  •  结果显示在标准输出设备上。

解题

  • 把方块看作是节点,相邻两个方块之间如果没 有墙,则在方块之间连一条边,这样城堡就能 转换成一个图。
  •  求房间个数,实际上就是在求图中有多少个极 大连通子图。
  •  一个连通子图,往里头加任何一个图里的其他 点,就会变得不连通,那么这个连通子图就是 极大连通子图。(如:(8,5,6))

对每一个房间,深度优先搜索,从而给这个房间能够到达的所有位置染色。最后统计一共用 了几种颜色,以及每种颜色的数量。

1 1 2 2 3 3 3

1 1 1 2 3 4 3

1 1 1 5 3 5 3

1 5 5 5 5 5 3

从而一共有5个房间,最大的房间(1)占据9 个格子

#include <iostream>
#include <stack>
#include <cstring>
#include <immintrin.h>
using namespace std;
int R,C;
int rooms[60][60];
int color[60][60];
int maxRoomArea=0;
int roomNum = 0;
int roomArea;
//深度优先搜索函数
void Dfs(int i,int k) {
    //如果该房间已经访问过,则返回
    if (color[i][k])
        return;
    //房间面积加1
    ++roomArea;
    //将该房间标记为已访问
    color[i][k]=1;
    //如果该房间与西边的房间连通,则继续搜索
    if( (rooms[i][k] & 1) == 0 ) Dfs(i,k-1);   //向西走
    //如果该房间与北边的房间连通,则继续搜索
    if( (rooms[i][k] & 2) == 0 ) Dfs(i-1,k);   //向北
    //如果该房间与东边的房间连通,则继续搜索
    if( (rooms[i][k] & 4) == 0 ) Dfs(i,k+1);  //向东
    //如果该房间与南边的房间连通,则继续搜索
    if( (rooms[i][k] & 8) == 0 ) Dfs(i+1,k);  //向南
}
int main() {
    //输入行数和列数
    cin>>R>>C;
    //输入每个房间的连通情况
    for (int i = 1; i <=R; ++i)
        for (int j = 1; j <=C; ++j)
            cin>>rooms[i][j];
    //遍历每个房间
    for (int i = 1; i <=R; ++i) {
        for (int k = 1; k <=C; ++k)
            //如果该房间未被访问过,则进行深度优先搜索
            if (!color[i][k]){
                //房间数量加1
                ++roomNum; roomArea=0;
                //进行深度优先搜索
                Dfs(i,k);
                //更新最大房间面积
                maxRoomArea=max(maxRoomArea,roomArea);
            }
        }
    //输出房间数量和最大房间面积
    cout<<roomNum <<endl;
    cout<<maxRoomArea<<endl;
}

输入

4

输出
11 6 11 6 3 10 6 
7 9 6 13 5 15 5 
1 10 12 7 13 7 5 
13 11 10 8 10 12 13
5
9

踩方格

有一个方格矩阵,矩阵边界在无穷远处。我们做如下假设:

a.每走一步时,只能从当前方格移动一格,走到某个相邻的方格上;

b. 走过的格子立即塌陷无法再走第二次;

c. 只能向北、东、西三个方向走;

请问:如果允许在方格矩阵上走n步(n<=20),共有多少种不同的方案。 2种走法只要有一步不一样,即被认为是不同的方案。

递归 从(i,j) 出发,走n步的方案数,等于以下三项之和:

从(i+1,j)出发,走n-1步的方案数。前提:(i+1,j)还没走过 从(i,j+1)出发

走n-1步的方案数。前提:(i,j+1)还没走过 从(i,j-1)出发

走n-1步的方案数。前提:(i,j-1)还没走过

#include <iostream>
#include <stack>
#include <cstring>
#include <immintrin.h>
using namespace std;
#include <iostream>
#include <cstring>
using namespace std;
// 定义一个二维数组,用于记录每个位置是否被访问过
int visited[30][50];
// 定义一个函数,用于计算从(i,j)位置出发,走n步的方案数
int ways ( int i,int j,int n)
{
    // 如果n为0,说明已经走完了n步,返回1
    if( n == 0)
        return 1;
    // 标记当前位置为已访问
    visited[i][j] = 1;
    int num = 0;
    // 如果当前位置的左边没有被访问过,则递归调用ways函数,计算从左边出发的方案数
    if( ! visited[i][j-1] )
        num+= ways(i,j-1,n-1);
    // 如果当前位置的右边没有被访问过,则递归调用ways函数,计算从右边出发的方案数
    if( ! visited[i][j+1] )
        num+= ways(i,j+1,n-1);
    // 如果当前位置的下边没有被访问过,则递归调用ways函数,计算从下边出发的方案数
    if( ! visited[i+1][j] )
        num+= ways(i+1,j,n-1);
    // 将当前位置标记为未访问
    visited[i][j] = 0;
    // 返回方案数
    return num;
}int main()
{
    int n;
    // 从标准输入读取n的值
    cin >> n;
    // 将visited数组初始化为0
    memset(visited,0,sizeof(visited));
    // 调用ways函数,计算从(0,25)位置出发,走n步的方案数,并输出结果
    cout << ways(0,25,n) << endl;
    return 0;
}

输入5
输出99


http://www.kler.cn/a/611736.html

相关文章:

  • ubuntu单机部署redis集群
  • HarmonyOS NEXT 鸿蒙中关系型数据库@ohos.data.relationalStore API 9+
  • IP 分片重组与 TCP 会话重组
  • 二分查找模板--从题目中讲解三大二分模板
  • [vue]计算属性
  • WPF ContentPresenter详解2
  • 网损仪详解
  • 比R版本快几十倍| Pyscenic单细胞转录因子预测
  • nVisual对接企业微信实现机房设备与连接变更的自动化审批
  • 硬件防火墙配置与优化:给网络装上最稳的安全阀
  • 深入探索 C++20 中的 std::make_obj_using_allocator
  • 使用Python可视化图结构:从GraphML文件生成节点关系图(lightrag 生成)
  • springcloud项目在框架搭建时的问题的总结
  • 使用HTTP提交git时,每次都要输入用户名和密码的解决方案
  • CentOS 7 宝塔部署
  • 【工具】openEuler 22.03 (LTS-SP3) 如何离线安装 git-lfs
  • Spring Boot集成阿里云OSS:对象存储实战指南
  • OpenBMC:BmcWeb 生效路由2 Trie字典树添加节点
  • vscode profile
  • 7.8 窗体间传递数据