【算法每日一练]-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;
}

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

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

相关文章

【ikbp】数据可视化DataV

天天查询一些数据&#xff0c;希望来一个托拉拽的展示&#xff0c;部署体验一下可视化大屏 快速搭建快速查询实时更新简单易用 启动服务 数据可视化 静态查询 配置数据 过滤数据 分享

计算机网络—网络搭建NAT内外网映射

使用Windows Server 2003 网络拓扑 Router 外网&#xff1a;NAT IP 网段 192.168.17.0/24内网&#xff1a;仅主机模式 IP 172.16.29.4 Client1&#xff1a;仅主机模式 IP 172.16.29.2 网关 172.16.29.1 Client2&#xff1a;仅主机模式 IP 172.16.29.3 网关 172.16.29.1…

数字信号处理期末复习——计算小题(二)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

uni-app中实现元素拖动

uni-app中实现元素拖动 1、代码示例 <template><movable-area class"music-layout"><movable-view class"img-layout" :x"x" :y"y" direction"all"><img :src"musicDetail.bgUrl" :class&…

SpringBoot实现Websocket聊天交友微信小程序(一)

记录一下我开发一个交友微信小程序并且上线运营的心得体会。 2022年10月1日上线的&#xff0c;到目前终于实现每天收益300左右。 界面比较简洁&#xff0c;功能有动态&#xff0c;动态可以选择话题&#xff0c;相册&#xff0c;相册可以设置看广告解锁&#xff0c;私信&#…

Kubernetes-网络

一. 前言 flannel两种容器跨主机通信的方案&#xff0c;其中UDP模式是IP in UDP&#xff0c;即三层报文封装在UDP数据包中通信&#xff1b;而vxlan模式则是MAC in UDP&#xff0c;即二层报文封装在UDP数据包中通信 flannel UDP模式和vxlan模式都对数据包做了封解包&#xff0c…

59.网游逆向分析与插件开发-游戏增加自动化助手接口-文字资源读取类的C++还原

内容来源于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;游戏菜单文字资源读取的逆向分析-CSDN博客 之前的内容&#xff1a;接管游戏的自动药水设定功能-CSDN博客 码云地址&#xff08;master分支&#xff09;&#xff1a;https://gitee.com/dye_your_fing…

2 Windows网络编程

1 基础概念 1.1 socket概念 Socket 的原意是“插座”&#xff0c;在计算机通信领域&#xff0c;socket 被翻译为“套接字”&#xff0c;它是计算机之间进行通信的一种约定或一种方式。Socket本质上是一个抽象层&#xff0c;它是一组用于网络通信的API&#xff0c;包括了一系列…

2024——剑之所至,所向披靡

目录 *年度总结导航 一.开篇——写在篇头 二.工作篇——心之所向 1.CSDN记录篇 1,1博客主页 1.2 第一篇博文 1.3.产品测试 1.4C站获奖博文 1.5团队创建 2.腾讯云记录篇 2.1博主的主页 2.2 博主好文推荐 2.3腾讯云产品体验 三.励志篇——未来可期 2023年计划 …

苹果cmsV10暗黑大气MT主题模板源码-只有PC版本

苹果cms MT主题是一款多功能苹果cmsV10暗黑大气主题 初次使用说明&#xff1a; 网站模板选择mt 模板目录填写html 后台地址&#xff1a;MT主题,mt/mtset 先应用主题打开前台&#xff0c;再点击后台。 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725…

网络安全—部署CA证书服务器

文章目录 网络拓扑安装步骤安装证书系统安装从属证书服务器 申请与颁发申请证书CA颁发证书 使用windows Server 2003环境 网络拓扑 两台服务器在同一网段即可&#xff0c;即能够互相ping通。 安装步骤 安装证书系统 首先我们对计算机名进行确认&#xff0c;安装了证书系统后我…

阿里云服务器8080端口安全组开通图文教程

阿里云服务器8080端口开放在安全组中放行&#xff0c;Tomcat默认使用8080端口&#xff0c;8080端口也用于www代理服务&#xff0c;阿腾云atengyun.com以8080端口为例来详细说下阿里云服务器8080端口开启教程教程&#xff1a; 阿里云服务器8080端口开启教程 阿里云服务器8080端…

如何在Mendix中实现全文检索

功能背景 在日常的应用使用过程中&#xff0c;存在大量希望使用全文检索技术的场景&#xff0c;对资料库中的内容进行查询。Mendix默认的结构化查询方式&#xff0c;适合对特定业务实体进行类似数据库单表的基于SQL语句的查询。那如何在Mendix实现全文检索的功能呢&#…

13.Go 异常

1、宕机 Go语言的类型系统会在编译时捕获很多错误&#xff0c;但有些错误只能在运行时检查&#xff0c;如数组访问越界、空指针引用等&#xff0c;这些运行时错误会引起宕机。 一般而言&#xff0c;当宕机发生时&#xff0c;程序会中断运行&#xff0c;并立即执行在该gorouti…

rk3588中编译带有ffmpeg的opencv

有朋友有工程需要&#xff0c;将视频写成mp4&#xff0c;当然最简单的方法当然是使用opencv的命令 cv::VideoWriter writer;bool bRet writer.open("./out.mp4", cv::VideoWriter::fourcc(m, p, 4, v), 15, cv::Size(640, 512), 1); 但是奈何很难编译成功&#xff…

go执行静态二进制文件和执行动态库文件

目的和需求&#xff1a;部分go的核心文件不开源&#xff0c;例如验证&#xff0c;主程序核心逻辑等等 第一个想法&#xff0c;把子程序代码打包成静态文件&#xff0c;然后主程序执行 子程序 package mainimport ("fmt""github.com/gogf/gf/v2/os/gfile"…

云服务器评估迁移时间与测试传输速度

迁移周期主要分为迁移前、迁移过程中、迁移后三部分。迁移周期时长与待迁移服务器的数量和实际数据量成正比&#xff0c;建议您根据实际迁移测试演练进行评估。本文主要介绍迁移过程中这一阶段所需时间的评估方式和传输速度的测试方法。 背景信息 在SMC迁移过程中&#xff0c…

UV打印机磁栅尺的安装

UV打印机磁栅尺的安装方法有以下几个注意事项&#xff1a; 1. 安装基面的选择&#xff1a;磁栅尺需要粘合在平滑的基面上&#xff0c;基面要足够平整且干净&#xff0c;不能有杂质或油污。 2. 粘合剂的选用&#xff1a;磁栅尺的粘合剂需要选用合适的胶水&#xff0c;最好是专门…

maven:在maven中使用tomcat7插件

1、在pom.xml中添加tomcat7插件 <build><!-- Embedded Apache Tomcat required for testing war --><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</ver…

【JavaFX】JavaFX11开发踩坑记录

文章目录 技术栈踩坑记录 技术栈 JavaFX 11MavenJDK 11 踩坑记录 这些坑对于初学者很容易踩&#xff0c;JavaFX经常会报错空指针异常遇到其中一个问题可能就会消耗好几天的时间。 JavaFX 采用的是MVC架构设计&#xff0c;页面设计使用 fxml文件&#xff1b;业务逻辑采用Con…