【算法每日一练]-dfs bfs(保姆级教程 篇8 )#01迷宫 #血色先锋队 #求先序排列 #取数游戏 #数的划分

目录

今日知识点:

使用并查集映射点,构造迷宫的连通块

vis计时数组要同步当回合的处理

递归求先序排列

基于不相邻的取数问题:dfs+回溯

n个相同球放入k个相同盒子:dfs的优化分支暴力

01迷宫

血色先锋队

求先序排列

取数游戏 

数的划分 


        

        

01迷宫

思路1:

其实啊:在写这个题的时候,总觉得这个题没法做,感觉时间复杂度非常高。因为一共(n*m)^4,一共这么格子,然后每个格子有4种选择…………

然后我犯了一个错误,其实dfs的复杂度不是这么看的,因为其实很多分支根本就没走。远远达不到那种耗时。就比如说正常的走迷宫问题,设置一个vis数组,然后dfs的复杂度最大也就整张地图罢了,根本不会达到每个点都做那么多个分支的情况数。所以哈。dfs的实际复杂度还得看实际的效果!扯远了………………

        

设置dfs(int x,int y,int z,int t)进行四个方向的暴搜就行,因为最多也就是搜1000次,然后本次搜索过的之后就不需要再搜索了,完全不会超时。   

#include <bits/stdc++.h>
using namespace std;
char s[1005][1005];
int n,m,ans[100005],f[1005][1005];
void dfs(int x,int y,int z,int t){if(x<0||y<0||x>=n||y>=n||f[x][y]!=-1||s[x][y]-'0'!=z)return ;ans[t]++;f[x][y]=t;dfs(x-1,y,!z,t);dfs(x,y-1,!z,t);dfs(x+1,y,!z,t);dfs(x,y+1,!z,t);
}
int main(){cin>>n>>m;int x,y;memset(f,-1,sizeof(f));for(int i=0;i<n;i++)cin>>s[i];for(int i=0;i<m;i++){scanf("%d%d",&x,&y);x--;y--;if(f[x][y]==-1){dfs(x,y,s[x][y]-'0',i);	}else{ans[i]=ans[f[x][y]];	}	}for(int i=0;i<m;i++)printf("%d\n",ans[i]);
}

其实你也看到了, 就是一道连通块的题,扫一下每个连通块内有多少个块罢了。

思路2:

既然都是连通块的题了,并查集做才最合理!

操作就是不断的去合并两个点,合并点的话需要进行映射(说白了就是找一个东西来唯一的表示这个点)最直接做法的就是映射成一维。最后合并的时候一边维护fa一边维护cnt就行了。

注意:千万不能从(0,0)开始,不然会映射失败。

#include <bits/stdc++.h>
using namespace std;
string s[1005];
int n,m;
int dx[]={0,-1,0,1},dy[]={1,0,-1,0};
int fa[1005*1005],cnt[1005*1005];
int real (int i,int j){return (i-1)*n+j;}int find(int x){if(x!=fa[x])fa[x]=find(fa[x]);return fa[x];
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++)cin>>s[i],s[i]="0"+s[i];int x,y,f1,f2;for(int i=1;i<=n*n;i++)fa[i]=i,cnt[i]=1;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=0;k<4;k++){x=i+dx[k];y=j+dy[k];if(x>=1&&y>=1&&x<=n&&y<=n&&s[x][y]!=s[i][j]){f1=find(real(i,j));f2=find(real(x,y));if(f1!=f2){fa[f2]=f1;cnt[f1]+=cnt[f2];}}}while(m--){scanf("%d%d",&x,&y);printf("%d\n",cnt[find(real(x,y))]);}
}

        

        

血色先锋队

  思路:

 有一种特别直接的做法:其实想找领主的最早感染时候,不过就是直接曼哈顿距离就能求出来了。那么求一个领主需要O(a)时间,找b个领主需要O(a*b)时间,不好意思直接会超时的。

所以这不是最聪明的做法,而是做不好的做法。

虽然说感染源很多,但是我们可以把这个感染源一起进行扩散,然后扩散整个图的时候,所有领主的感染时间也就确定了。仅需要一张图的时间罢了。

这里有个bug改了好久才发现,vis标记一定要同步于当回合处理。

(果然,迷迷糊糊的时候尽量不要敲代码啊)

#include <bits/stdc++.h>
using namespace std;
int a,b,n,m;
int vis[550][550];
struct node{int x;int y;};
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
int main(){cin>>n>>m>>a>>b;int x,y,t=0;memset(vis,-1,sizeof(vis));queue<node>q;for(int i=1;i<=a;i++){scanf("%d%d",&x,&y);q.push(node{x,y});vis[x][y]=t;//入队就标记:一定要当回就标记,避免下回合开始之后上回合还没有标记}while(!q.empty()){int sz=q.size();t++;while(sz--){node cur=q.front();q.pop();for(int i=0;i<4;i++){int tx=cur.x+dx[i],ty=cur.y+dy[i];if(tx<1||ty<1||tx>n||ty>m||vis[tx][ty]!=-1)continue;q.push(node{tx,ty});vis[tx][ty]=t;//在利用队列中点进行下一层处理时候,当前队列的所有点均已经安全标记}	}}for(int i=1;i<=b;i++){scanf("%d%d",&x,&y);printf("%d\n",vis[x][y]);}
}

        

         

求先序排列

思路:

一道dfs题的老朋友了。 

直接模拟就行:给个例子:中序ACGDBHZKX,后序CDGAHXKZB

找到主根B,然后左子树(ACGD,CDGA)重复操作,右子树(HZKX,HXKZ)重复操作即可。

然后注意输出是先序,所以先输出根,然后递归左边,最后是右边。

最最后注意结束条件就行了(长度为1就结束,不要进入错误操作)

#include <bits/stdc++.h>
using namespace std;void dfs(string s1,string s2){int sz1=s1.size(),sz2=s2.size();if(sz1==1){cout<<s1;return ;}string s11,s12,s21,s22;char ch=s2[sz2-1];int i=s1.find(ch);s11=s1.substr(0,i);s12=s1.substr(i+1);	s21=s2.substr(0,i);s22=s2.substr(i,sz2-i-1);cout<<ch;if(s11.size())dfs(s11,s21);if(s12.size())dfs(s12,s22);
}
int main(){string s1,s2;cin>>s1>>s2;dfs(s1,s2);
}

        

         

取数游戏 

思路:

我一开始的思路是dfs(x1,y1,x2,y2)然后转移到下一个(i,j,i+1,j+1)也就是用i+1,j+1来标记走过的状态。嗯~ 后面再一看,我去,这样子只能不与上一个状态冲突,那么和上上个状态就冲突。反正就是必须整个图都要进行标记,我标记的不够。

那么就dfs+回溯,进行全图标记。

 首先装模装样的分析一下dfs的时间复杂度:首先基于回溯的话,每个格子妥妥的要跑2种状态。一共36个格子,所以2^36??? 等等,因为是跳着走的,所以因为2^18左右吧(其是不是很会)

#include <bits/stdc++.h>
using namespace std;
const int d[8][2]={1,0,-1,0,0,1,0,-1,1,1,-1,1,1,-1,-1,-1};
int ans,n,m,t;
int vis[8][8],a[8][8];void dfs(int x,int y,int mx){if(y==m+1){dfs(x+1,1,mx);return ;}if(x==n+1){ans=max(ans,mx);return ;}dfs(x,y+1,mx);if(vis[x][y]==0){for(int i=0;i<8;i++){vis[x+d[i][0]][y+d[i][1]]++;}dfs(x,y+1,mx+a[x][y]);for(int i=0;i<8;i++){vis[x+d[i][0]][y+d[i][1]]--;}}
}
int main(){cin>>t;while(t--){ans=0;memset(a,0,sizeof(a));memset(vis,0,sizeof(vis));cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>a[i][j];dfs(1,1,0);cout<<ans<<'\n';}
}

        

         

数的划分 

思路:

两种做法:

第一种:动态规划:

题目可以理解成把n个相同球放入k个相同盒子,然后因为球都是相同的,就不能再对最后一个球进行讨论了。应该对应一类球:

设置a[i][j]表示i个球放入j个盒子的方案数。

第一种情况:有一个盒子只有一个球,那么就对应了a[i-1][j]

第二种情况:每个盒子都至少有两个球,那么就对应看a[i-j][j]

所以:a[i][j]=a[i-j][j]+a[i-1][j-1]

第二种:dfs:

在已经放了i时候,每次可以放1~n-i个,所有dfs(i)有n-i个分支,这个复杂度很高,别着急,只需要把无效分支剔除即可很快。

仔细观察7的拆法:

1 1 5

1 2 4

1 3 3

2 2 3

2 3 2(重复了哟)

所以你发现了,要想不重复 ,就必须后面选的数比前面的大,(很早的时候我们再输出组合数的时候就是这样子去重的,只需要安排升序即可),所以在dfs(i)也就是选了i的时候,后面选的数都必须比i大,那么有了sum+i*(k-cnt)<=n这个分支优化。

dfs的速度就变快了很多。

#include <bits/stdc++.h>
using namespace std;
int n,k,ans=0,a[205][70];
//int main(){
//	cin>>n>>k;
//	for(int i=1;i<=n;i++)a[i][1]=1;
//	for(int i=2;i<=n;i++)
//		for(int j=2;j<=(i,k);j++){
//			a[i][j]=a[i-1][j-1];
//			if(i>=2*j)a[i][j]+=a[i-j][j];
//		}
//	cout<<a[n][k];
//}
void dfs(int cnt,int up,int sum){if(cnt==k){if(sum==n)ans++;return ;}for(int i=up;sum+i*(k-cnt)<=n;i++){dfs(cnt+1,i,sum+i);}
}
int main(){cin>>n>>k;dfs(0,1,0);cout<<ans;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Javaweb之Mybatis的基础操作的详细解析

1. Mybatis基础操作 学习完mybatis入门后&#xff0c;我们继续学习mybatis基础操作。 1.1 需求 需求说明 通过分析以上的页面原型和需求&#xff0c;我们确定了功能列表&#xff1a; 查询 根据主键ID查询 条件查询 新增 更新 删除 根据主键ID删除 根据主键ID批量删除 …

七:Day06_redis高级01

第一章 Redis入门 1.1 节 什么是NoSql型数据库 NoSQL ,泛指非关系型的数据库, NoSQL Not Only SQL,它可以作为关系型数据库的良好补充。NoSQL 不依赖业务逻辑方式存储&#xff0c;而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。 SQLNoSQL数据结构结构化非…

【K8S 资源管理】声明式资源管理

目录 一、常用的发布方式 1、蓝绿发布&#xff1a; 2、金丝雀发布&#xff08;灰度发布&#xff09;&#xff1a; 3、滚动更新&#xff08;deployment的默认更新方式&#xff09;&#xff1a; 二、声明式管理方法&#xff08;yaml文件&#xff09; 1、三种发布命令&#x…

数据结构第2章 栈和队列

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 本篇笔记整理&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 0、思维导图栈和队列1、栈1&#xff09;特点2&#xff0…

技术资讯:Vue 3.4 新版本发布,1分钟快速看看改了啥!

大家好&#xff0c;我是大澈&#xff01; 本文约1000字&#xff0c;整篇阅读大约需要1分钟。 感谢关注微信公众号&#xff1a;“程序员大澈”&#xff0c;免费领取"面试礼包"一份&#xff0c;然后免费加入问答群&#xff0c;从此让解决问题的你不再孤单&#xff01…

SpringMVC框架

SpringMVC 三层架构MVC模式SpringMVC入门案例总结 三层架构 表现层&#xff08;web&#xff09; 页面数据的收集&#xff0c;产出页面 业务逻辑层&#xff08;service&#xff09; 业务处理 数据访问层&#xff08;Dao&#xff09; 数据持久化 MVC模式 SpringMVC 基于Java…

单元测试框架-Unittest

1 Selenium自动化测试基础和环境部署 1.Web功能自动化测试——为什么要学习单元测试框架unittest?除此之外还有没有其他的单元测试框架&#xff1f; Python语言编写的WebDriver测试脚本通常使用单元测试框架来运行&#xff0c;所以&#xff0c;了解单元测试框架的基本方法和…

【日积月累】Java Lambda 表达式

目录 【日积月累】Java Lambda 表达式 1.前言2.语法3.应用场景3.1简化匿名内部类的编写3.1简化匿名内部类的编写3.2简化集合类中的操作3.3实现函数式接口3.4简化多个方法的调用3.5简化异步编程 4.总结5.参考 文章所属专区 日积月累 1.前言 Lambda表达式是一个匿名函数&#…

useState和setState区别

一、主要是讲一下类组件的状态和函数组件的状态 1.类组件中state只能有一个&#xff0c; 函数组件中state可以有多个 函数组件&#xff1a;可以使用对个状态&#xff0c;便于控制。 // 文章数量的初始值const [articleData, setArticleData] useState({list: [],// 文章列表…

k8s 之7大CNI 网络插件

一、介绍 网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求&#xff0c;但在实现方面也具有一定的灵活性。因此&#xff0c;业界已有不少不同的网络方案&#xff0c;来满足特定的环境和要求。 CNI意为容器网络…

基于混合蛙跳算法优化的Elman神经网络数据预测 - 附代码

基于混合蛙跳算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于混合蛙跳算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于混合蛙跳优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&…

在pbootcms中制作静态化的TAG标签列表

如果你使用pbootcms来管理你的网站&#xff0c;你可能会遇到这样的需求&#xff1a;将TAG标签列表改成静态化的类似于栏目结构的需求。下面是实现这个需求的步骤。 步骤1 修改PHP文件 打开 apps/home/controller/ParserController.php 并找到大约在1852行左右的代码段&#x…

2024年测试岗最新自动化测试面试题整理,干货满满

一、接口测试 1、接口测试用例的编写要点有哪些&#xff1f;&#xff08;问法二&#xff1a;接口测试用例设计需要考虑哪些方面&#xff1f;问法三&#xff1a;接口测试中有哪些要注意的测试点&#xff1f;&#xff09; 1&#xff09; 考虑输入参数和输出参数的合法性&#x…

SQL窗口函数大小详解

窗口大小 OVER 子句中的 frame_clause 选项用于指定一个滑动的窗口。窗口总是位于分区范围之内&#xff0c;是分区的一个子集。指定了窗口之后&#xff0c;分析函数不再基于分区进行计算&#xff0c;而是基于窗口内的数据进行计算。 指定窗口大小的语法如下&#xff1a; ROWS…

java进阶四-深入理解泛型和注解

泛型和注解是框架技术必备的技能 5 泛型5.1泛型理解5.1.1 泛型概念5.1.2 泛型的特点5.1.3 如何理解Java中的泛型是伪泛型&#xff1f;5.1.4 泛型的价值 5.2 泛型语法5.2.1 泛型类5.2.2 泛型接口3.2.3 泛型方法3.2.4泛型的上下边界3.2.5创建泛型数组 5.3泛型应用场景5.3.1数据库…

(七)独立按键

文章目录 独立按键原理图三行代码法简单概述代码书写键码推算如何使用短按键长按键 状态机法简单概述代码书写键码推算如何使用短按键长按键 现象 独立按键原理图 三行代码法 简单概述 代码书写 u8 Trg 0x00;//短按键 u8 Cont 0x00;//长按键 void BtnThree(void) {u8 reada…

CMake入门教程【核心篇】安装(install)

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1. 概述2. 使用方法2…

如何从零开始搭建公司自动化测试框架?

一、为什么要搭建自动化测试框架 测试如果按照是否手工划分&#xff0c;可以分为“手工测试”和“自动化测试”。 “手工测试”也就是用人力来进行功能测试。相比自动化测试而言执行效率慢&#xff0c;可以进行探索性测试和发散性测试。 “自动化测试”主要是通过所开发的软…

Python控制程控电源(USB)

文章目录 前言一、环境搭建1.软件安装2.硬件安装二、设置程控电源连接方式三、Python代码四、验证结果五、pyd文件前言 随着智能电动汽车行业的持续发展,汽车电子或嵌入式设备在软硬件的测试中,都会使用程控电源供电,特别是自动化测试、压力测试场景必定使用到程控电源控制…

nifi详细介绍--一款开箱即用、功能强大可靠,可用于处理和分发数据的大数据组件

目录 目录 一、引言 二、NiFi 的历史背景介绍 三、NiFi 是什么&#xff1f; 核心特性 应用领域 四、NIFI 入门 五 、NiFi 工作流程 六、实际应用场景 七、优势总结 一、引言 NiFi&#xff08;Apache NiFi&#xff09;&#xff0c;全名为“Niagara Files”&#xff0…