DFS——连通性和搜索顺序

dfs的搜索是基于栈,但一般可以用用递归实现,实际上用的是系统栈。有内部搜索和外部搜索两种,内部搜索是在图的内部,内部搜索一般基于连通性,从一个点转移到另一个点,或者判断是否连通之类的问题,只需要标记避免重复访问即可,不需要还原状态,而外部搜索则是将一张图视为一种状态,每一个状态延伸得到新的状态,要保证每个状态往外延伸时都是相同的,那么就需要还原状态。

搜索顺序也很重要,我们要找到合适的搜索顺序保证不漏的搜出每一种情况,重复当然没什么问题。

另外,同宽搜相比,深搜的代码会简单一些,但是却有爆栈的风险,递归层数比较高的时候需要注意。

1112. 迷宫(活动 - AcWing)

思路:本质上就是判断能不能从这点到达另一点,那么就是连通性问题,深搜宽搜都可以,这里我们用深搜来实现。

#include<bits/stdc++.h>
using namespace std;
int n;
char s[120][120];
int sx,sy,ex,ey;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int st[120][120];
int dfs(int x,int y)
{
    if(s[x][y]=='#') return 0; 
    if(x==ex&&y==ey) return 1;
    st[x][y]=1;
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i],ny=y+dy[i];
        if(nx<0||nx>=n||ny<0||ny>=n) continue;
        if(st[nx][ny]) continue;
        if(dfs(nx,ny)) return 1;
    }
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%s",s[i]);
        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
        if(dfs(sx,sy)) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
        memset(st,0,sizeof st);
    }
}

1113. 红与黑(1113. 红与黑 - AcWing题库)

思路:实际上就是统计一个连通块内有多少个元素。

#include<bits/stdc++.h>
using namespace std;
char g[30][30];
int n,m;
int cnt;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int st[30][30];
void dfs(int x,int y)
{
    st[x][y]=1;
    cnt++;
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i],ny=y+dy[i];
        if(nx<0||nx>=n||ny<0||ny>=m) continue;
        if(st[nx][ny])continue;
        if(g[nx][ny]=='#') continue;
        dfs(nx,ny);
    }
}
int main()
{
    while(scanf("%d%d",&m,&n))
    {
        if(!n&&!m) break;
        for(int i=0;i<n;i++) scanf("%s",g[i]);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(g[i][j]=='@')
                {
                    cnt=0;
                    dfs(i,j);
                    cout<<cnt<<endl;
                    break;
                }
        memset(st,0,sizeof st);
    }
}

 1116. 马走日(活动 - AcWing)

思路:这题看似是说在棋盘内部移动,但实际上每次统计一个结果的前提是整个棋盘都被遍历,而且每一步移动有八个选择(理想情况),八个选择各自代表不同的状态,所以我们需要还原状态,只用在最后递归到所有节点都访问过时,记录一下即可。

#include<bits/stdc++.h>
using namespace std;
int n,m;
int st[10][10];
int ans;
int dx[]={1,1,-1,-1,2,2,-2,-2};
int dy[]={2,-2,2,-2,1,-1,1,-1};
void dfs(int x,int y,int k)
{
    if(k==n*m) 
    {
        ans++;
        return;
    }
    st[x][y]=1;
    for(int i=0;i<8;i++)
    {
        int nx=x+dx[i],ny=y+dy[i];
        if(nx<0||nx>=n||ny<0||ny>=m) continue;
        if(st[nx][ny]) continue;
        dfs(nx,ny,k+1);
    }
    st[x][y]=0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int x,y;
        scanf("%d%d%d%d",&n,&m,&x,&y);
        ans=0;
        dfs(x,y,1);
        cout<<ans<<endl;
    }
}

ps:特殊情况单独判返回的时候一定要注意状态有没有请干净。

1117. 单词接龙(活动 - AcWing)

思路:这里首先要想搜索,我们需要建立单词与单词之间的关系,准确来说我们需要知道哪些单词可以接在哪些单词的后面,它们的重合长度是多少,这里的重合长度一定要越小越好,因为我们可以任意选择重合长度。

那么预处理完之后,直接深搜记录最大值即可。

另外要注意每个单词只能用两次,那么需要记录一下当前单词已经用了几次了,我们可以用下标来实现。

#include<bits/stdc++.h>
using namespace std;
int n;
string s[30];
int used[30];
int g[30][30];
int mx;
void dfs(string r,int k)
{
    if(used[k]==2) return;
    used[k]++;
    for(int i=0;i<n;i++)
    {
        if(g[k][i]&&used[i]<2)
        {
            
            string tmp=r+s[i].substr(g[k][i]);
            //cout<<r<<" "<<s[i].substr(g[k][i])<<" "<<g[k][i]<<endl;
            mx=max(mx,(int)tmp.size());
            dfs(r+s[i].substr(g[k][i]),i);
        }
    }
    used[k]--;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) cin>>s[i];
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=1;k<min(s[i].size(),s[j].size());k++)
            {
                if(s[i].substr(s[i].size()-k,k)==s[j].substr(0,k))
                {
                    g[i][j]=k;
                    break;
                }
            }
            //printf("%d ",g[i][j]);
        }
        //printf("\n");
    }
    char c;
    cin>>c;
    mx=0;
    for(int i=0;i<n;i++)
    {
        if(s[i][0]==c)
        {
            mx=max(mx,(int)s[i].size());
            dfs(s[i],i);
        }
    }
    cout<<mx;
}

 1118. 分成互质组(活动 - AcWing)

思路:如果我们将第一个数放在第一组,那么遍历后面的数,如果不与第一组中的数互质,那么就可以放进这一组,否则就只能新开一组,如此递归来实现,就可保证将所有的数都分好组,同时是分组最少的。

另外由于放进同一个组内的顺序无所谓,所以当不用新开一个组的时候,遍历下一层的时候,直接从后一个元素开始遍历,否则,如果新开组,那么就要从开头开始遍历。因为是按顺序遍历的,所以当前元素被遍历前,它之前的元素与这一组的关系都已经判断过了,所以如果不新开组那么就没必要再往前看。

#include<bits/stdc++.h>
using namespace std;
int n;
int a[20];
int g[20][20];
int ans=10;
int st[20];
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
int check(int u,int g[],int cn)
{
    for(int i=0;i<cn;i++)
    {
        if(gcd(a[u],a[g[i]])>1) return 0; 
    }
    return 1;
}
void dfs(int u,int c,int k,int cn)//u是此时从哪个点开始判断,c是当前处在第几个组,k是已经分配几个点了,cn当前组中有多少个元素
{
    if(c>=ans) return;
    if(k==n)
    {
        ans =min(ans,c);
        return;
    }
    int flag=1;
    for(int i=u;i<n;i++)
    {
        if(!st[i]&&check(i,g[c],cn))//一个点都不能放入了再新开
        {
            st[i]=1;
            g[c][cn]=i;
            dfs(u+1,c,k+1,cn+1);
            st[i]=0;
            
            flag=0;
        }
    }
    if(flag) dfs(0,c+1,k,0);
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    dfs(0,1,0,0);
    cout<<ans;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/371578.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

react将选中本文自动滑动到容器可视区域内

// 自动滚动到可视区域内useEffect(() > {const target ref;const wrapper wrapperRef?.current;if (target && wrapperRef) {const rect target.getBoundingClientRect();const wrapperRect wrapper.getBoundingClientRect();const isVisible rect.bottom &l…

如何选择日本大带宽服务器?

随着互联网的高速发展&#xff0c;对于大带宽服务器的需求也日益增长。而在日本&#xff0c;由于其先进的网络基础设施和数据中心技术&#xff0c;大带宽服务器成为了许多企业和开发者的首选。那么&#xff0c;如何选择合适的日本大带宽服务器呢? 首先&#xff0c;了解自己的需…

linux☞ Centos 基础篇

切换用户 重启系统、退出 su 用户 ### su switch user 重启系统 reboot 退出当前账户 logout 或者 exit 或者 CtrlD 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33 TYPEEthernet&#xff1a;指明网卡类型为以太网 DEVICEens33&#xff1a;指定当前配置的…

c++类和对象(二)

类与对象 一.类的6个默认成员函数1.1类的6个默认成员函数 二.构造函数2.1.1构造函数的概念2.1.2构造函数的特性 三.析构函数3.1.1概念3.1.2特点 四.拷贝函数4.1.1概念4.1.2特征 一.类的6个默认成员函数 1.1类的6个默认成员函数 在C中&#xff0c;如果在一个类中什么成员都没有…

docker maven插件使用介绍

1、配置docker连接 开放docker tcp连接参考本专栏下令一篇文章 2、docker service窗口 3、根据dockerfile 构建镜像 注意 idea 用通过管理员身份启动&#xff0c;否则连不上docker 构建前添加maven goal 打包 4、运行镜像 创建容器 5、运行docker compose 报错 需要先配置d…

Java并发之synchronized详解

☆* o(≧▽≦)o *☆嗨~我是小奥&#x1f379; &#x1f4c4;&#x1f4c4;&#x1f4c4;个人博客&#xff1a;小奥的博客 &#x1f4c4;&#x1f4c4;&#x1f4c4;CSDN&#xff1a;个人CSDN &#x1f4d9;&#x1f4d9;&#x1f4d9;Github&#xff1a;传送门 &#x1f4c5;&a…

QtAV学习:(一)Windows下编译QtAV

QtAV 主页&#xff1a; QtAV by wang-bin 作者的编译构建说明文档&#xff1a; Build QtAV wang-bin/QtAV Wiki GitHub 我的编译环境&#xff1a; 编译环境&#xff1a;win10/msvc2015/Qt5.6.3 第一步&#xff1a;GitHub拉取代码,执行子模块初始化 地址&#xff1a; …

web前端-------弹性盒子(2)

上一讲我们谈的是盒子的容器实行&#xff0c;今天我们来聊一聊弹性盒子的项目属性&#xff1b; *******************&#xff08;1&#xff09;顺序属性 order属性&#xff0c;用于定义容器中项目的出现顺序。 顺序属性值&#xff0c;为整数&#xff0c;可以为负数&#xff…

数仓建设规范

目录 前言 一、数据模型设计规范 1.1 数仓分层原则 1.2 主题域划分原则 1.3 数据模型设计原则 1.4 数据模型管理的目标 1.5 数仓建模的方法 1.5.1 维度建模 1.5.2 三范式建模 1.5.3 三范式与维度建模区别 二、数仓公共开发规范 2.1 层次调用规范 2.2 数据类型规范…

redis(4)

文章目录 一、redis主从复制redis 主从复制架构主从复制实现命令行配置同步日志修改slave节点配置文件 主从复制故障恢复主从复制故障恢复过程介绍主从复制故障恢复实现 实现redis的级联复制主从复制优化主从复制过程主从同步优化配置 常见主从复制故障汇总master密码不对Redis…

C系列-柔性数组

&#x1f308;个人主页: 会编程的果子君 ​&#x1f4ab;个人格言:“成为自己未来的主人~” 目录 ​编辑 柔性数组 柔性数组的特点 柔性数组的使用 柔性数组的优势 柔性数组 也许你从来没有听说过柔性数组这个概念&#xff0c;但是它确实是存在的&#xff0c;C99中&#…

python 安装 流程

1. 下载python解析器。&#xff08;根据软件安装提示&#xff0c;傻瓜式操作。勾选 将其添加到path 环境变量&#xff09;Download Python | Python.org 2. 在Python环境中 安装selenium模块 命令行中 运行 pip install selenium 如果你使用的是Python3&#xff0c;可能需要…

list基本使用

list基本使用 构造迭代器容量访问修改 list容器底层是带头双向链表结构&#xff0c;可以在常数范围内在任意位置进行输入和删除&#xff0c;但不支持任意位置的随机访问&#xff08;如不支持[ ]下标访问&#xff09;&#xff0c;下面介绍list容器的基本使用接口。 template <…

租用海外服务器丢包是什么情况?

在当今的互联网时代&#xff0c;海外服务器租用已经成为了许多企业和个人的选择。然而&#xff0c;在使用海外服务器的过程中&#xff0c;有时会出现丢包的情况&#xff0c;这给用户带来了不小的困扰。那么&#xff0c;租用海外服务器丢包是什么情况呢&#xff1f;本文将对此进…

Java Arrays 的相关操作数组排序

Java Arrays 的相关操作数组排序 package com.zhong.arrays;import java.math.BigDecimal; import java.util.Arrays; import java.util.Comparator;public class ArraysDemo {public static void main(String[] args) {int[] arr {10, 20, 40, 30, 90, 60, 10, 30, 50};// A…

profinet转CANopen网关在博图如何配置profinet从站步骤

Profinet转CANopen网关&#xff08;XD-COPNm20&#xff09;是一种用于实现CANopen设备与Profinet网络连接起来进行设备之间的数据交换和通信的设备。CANopen和Profinet是两种常见的工业通信协议&#xff0c;它们在自动化控制系统中有着广泛的应用。因此CANopen转Profinet网关在…

k8s-常用工作负载控制器(更高级管理Pod)

一、工作负载控制器是什么&#xff1f; 二、Deploymennt控制器&#xff1a;介绍与部署应用 部署 三、Deployment控制器&#xff1a;滚动升级、零停机 方式一&#xff1a; 通个加入健康检查可以&#xff0c;看到&#xff0c;nginx容器逐个被替代&#xff0c;最终每个都升级完成&…

前端学习第4天

一、复合选择器 1.后代选择器 2.子代选择器 3.并集选择器 4.交集选择器 5.伪类选择器 1.伪类-超链接&#xff08;拓展&#xff09; 二、CSS特性 1.继承性 body放在style中 2.层叠性 3.优先级 属性 !important;&#xff08;最高优先级&#xff09; 1.优先级-叠加计算规则 2.em…

zabbix监控mariadb数据库

zabbix监控mariadb数据库 1.创建监控用户及授权 [rootchang ~]# mysql -uroot -p123qqq.A MariaDB [(none)]> CREATE USER monitor% IDENTIFIED BY 123qqq.A; MariaDB [(none)]> GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO monitor%; Maria…

Vue中nextTick方法的作用与原理

在Vue的开发中&#xff0c;你可能会遇到一些异步更新的问题&#xff0c;如在改变数据后需要等待DOM更新完毕后再进行下一步操作。这时就可以使用Vue提供的nextTick方法来解决这个问题。 nextTick方法的作用是在DOM更新之后执行回调函数&#xff0c;确保在下次DOM更新循环结束之…