10月18日DFS测试复盘

本次博客回顾了近期的DFS测试,涉及多个题目,包括01迷宫、观星、FBI树和单词方阵。针对每个问题,强调了算法优化的重要性,如使用数组记录答案、注意数据范围调整等。通过深入探讨二叉树的应用和理解,揭示了在解决复杂问题时如何巧妙运用DFS。
摘要由CSDN通过智能技术生成

p1141(01迷宫)
题目传送们


题目不难

但有很多细节要注意 

首先如果每一个都去求一遍连通块

时间复杂度较高(o(n*n*m))会爆炸

于是我们就想到了拿数组记录答案

记得数组要开大一点

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,id=0,p,q,num=0;
int a[1000005];
string s[1001]; 
bool vis[1005][1005];
int ps[1005][1005];
int dx[10]={1,-1,0,0},dy[10]={0,0,1,-1};
void dfs(int x,int y){
	num++;	
	ps[x][y]=id;
	vis[x][y]=1;
	for(int i=0;i<4;i++){
		int nx= x+dx[i];
		int ny= y+dy[i];
		if(nx >= 0 and ny >= 0 and nx < n and ny < n and s[nx][ny] != s[x][y] and vis[nx][ny] == 0){
			dfs(nx,ny);
		}
	}
	return;
}
int main(){
	cin >> n >> m;
	for(int i=0;i<n;i++){
		cin >> s[i];
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(vis[i][j] != 1){
				id++;
				num=0;
				dfs(i,j);
				a[id]=num;
			}
		}
	}
	while(m--){
		cin >> p >> q;
		p--, q--;
		cout << a[ps[p][q]] << endl;
	}
}

p6566(观星)

题目传送门


和普通的连通块差不多

只是由于星系的原因

需要用数组存一下再按规则变化

切记(看数据范围调整数组大小)

代码:

#include<bits/stdc++.h>
using namespace std;
string s[300000];
int n,m,res=0,shixuanzhety_is=0,sb=0,pop=0;
bool vis[3000][3000];
int dx[30]={1,1,-1,-1,1,-1,0,0};
int dy[30]={-1,1,-1,1,0,0,1,-1};
int a[300000];
void dfs(int x,int y){
	shixuanzhety_is++;
	vis[x][y]=1;
	for(int i=0;i<8;i++){
		int xxx=x+dx[i];
		int yyy=y+dy[i];
		if(xxx > 0 and xxx <= n and yyy > 0 and yyy <= m and s[xxx][yyy] != '.' and !vis[xxx][yyy]){
			dfs(xxx,yyy);
		}
	}
}
int main(){
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		cin >> s[i];
		s[i] = " "+s[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(!vis[i][j] and s[i][j] != '.'){
				shixuanzhety_is=0;
				dfs(i,j);
				a[shixuanzhety_is]++;
				sb=max(shixuanzhety_is,sb);
			}
		}
	}
	for(int i=1;i<=sb;i++){
		if(a[i] != 0){
			res++;
			pop=max(pop,i*a[i]);
		}
	}
	cout << res << ' ' << pop << endl;
	return 0;	
} 


p1087(FBI树)

 题目传送门


此题考察的是对二叉树的应用和理解

每次用find来求当前是F,B,I 中的哪一个

先dfs()左右两个子树,再输出

若当前的字符串长度为一

则无法分2段找左右

直接输出即可

代码:

#include<bits/stdc++.h>
using namespace std;
string b;
int s;
int re=0;
void print(int o,int l){
	if(o != -1 and l != -1){
		cout << "F";
	}else if(l != -1){
		cout << "I";
	}else{
		cout << "B";
	}
	return;
}
void dfs(string x){
	int xx=x.size(),l=x.find('1'),o=x.find('0');
	if(xx>1){
		dfs(x.substr(0,xx/2));
		dfs(x.substr(xx/2));
		print(o,l);
		return;
	}	
	print(o,l);
}
int main(){
	cin >> s >> b;
	dfs(b);
	return 0;	
} 

p1101(单词方阵)

题目传送门 


咋一看,数据范围(1000)感觉不能搜索的样子

但是这题搜到一个点后面的顺序就是固定的了

那就只有8个方向了

答案用标记数组一标记就可以了

代码:

#include<bits/stdc++.h>
using namespace std;
string b[22222],h=" yizhong";
int s,n;
bool vis[2222][2222];
int re=0;
int dx[30]={1,1,-1,-1,1,-1,0,0};
int dy[30]={-1,1,-1,1,0,0,1,-1};
void check(int x,int y,int d){
	for(int i=1;i<=7;i++){
		vis[x][y]=1;
		x-=dx[d];
		y-=dy[d];
	}
	return;
}
void dfs(int x,int y,int d,int cur){
	if(cur == 7){
		check(x,y,d);
		return;
	}
	int xxx=x+dx[d];
	int yyy=y+dy[d];
	if(xxx > 0 and xxx <= n and yyy > 0 and yyy <= n and b[xxx][yyy] == h[cur+1]){
		dfs(xxx,yyy,d,cur+1);
	}
}
int main(){
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> b[i];
		b[i]=" "+b[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(b[i][j] == 'y'){
				for(int d=0;d<8;d++){
					dfs(i,j,d,1);
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(vis[i][j]){
				cout << b[i][j];
			}else{
				cout << '*';
			}
			
		}
		cout << endl;
	}
	return 0;	
} 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值