算法笔记学习记录(3)--DFS与BFS

算法笔记学习记录(3)


深度优先遍历(DFS)和广度优先遍历(BFS)是计算机专业学生很经常听到的算法,但也许很多人并没有怎么接触,其实这两个算法非常方便好用,形式也简明,但要注意的是对递归要有比较清楚地理解。

深度优先遍历
设想有一个迷宫,深度优先遍历的思想是尽可能的“一条道走到黑”,路上会碰到很多岔道口(每一步都有多种情况),先选择其中一条走,如果碰见了死胡同则返回,直到找到走出出口的那一条路径,故深度优先搜索就是一种枚举所有完整路径以遍历所有情况的搜索方法。
回想递归的思想,最重要的是找到递归式递归边界
,递归式就是岔道口,递归边界就是死胡同

例子:给定N个整数,从中选择K个数,使得这K个数之和恰好等于一个给定的整数X,如果有多重方案,选择他们中元素平方和最大的一个,数据保证这样的方案唯一。`
此题中的岔道口就是每次选择的数,共选K个数(很多种组合),死胡同就是选择K个数且和等于X时(这就是一条完整的“路”)。

#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;

const int maxn = 30;
//n个数选k个数使得和为x,最大平方和为maxsumsqu 
int n,k,x,maxsumsqu = -1, A[maxn];
vector<int> temp,ans;
//temp存放临时方案,ans存放平方和最大的方案 
//当前处理index号整数,当前 已选整数个数为nowK
//当前已选整数之和为sum,当前已选整数平方和为sumsqu

void DFS(int index,int nowk,int sum,int sumsqu){
//死胡同
	if(nowk == k && sum==x){  //找到K个数的和为x ,判断大小 
		if(sumsqu > maxsumsqu){
			maxsumsqu = sumsqu;
			ans = temp;
		} 
		return;
	} 
	//已经处理完N个数,或者超过k个数,或者和超过x
	if(index==n||nowk>k||sum>x) return; 
	
	//岔路口
	//选index
	temp.push_back(A[index]) ;
	DFS(index + 1,nowk+1,sum+A[index],sumsqu+A[index]*A[index]); //若数可以重复选择,则,index+1选为index
	temp.pop_back();
	//不选index
	DFS(index + 1,nowk,sum,sumsqu); 
}

int main(){
	scanf("%d%d%d",&n,&k,&x);
	for(int i=0;i<n;i++){
	scanf("%d",&A[i]); 
}
	DFS(0,0,0,0);
	printf("%d",maxsumsqu);
}

广度优先遍历
广度优先遍历,更像是随着一个中心一圈一圈的划出范围,然后依次访问从该岔道口能直接到达的所有结点,然后再按这些结点被访问的顺序去依次访问他们能直接到达的所有结点,且总是按着层次的顺序进行遍历。
void BFS(int s) {
queue q;
q.push(s);
while(!q.empty()) {
取出队首元素top;
访问队首元素top;
将队首元素出队;
将top的下一层节点中未曾入队的节点全部入队,并设置为已入队。
}

在这里插入图片描述

BFS:
#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;
const int maxn =30;
int matrix[maxn][maxn];
bool inq[maxn][maxn]={false};
int n,m;

struct node{
	int x;
	int y;
}Node;

int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};

bool judge(int x,int y){//判断坐标是否需要访问 
	if(x>=n||x<0||y>=m||y<0) return false;
	if(matrix[x][y]==0||inq[x][y]==true) return false;
	return true;
}

void BFS(int x,int y){
	queue<node> Q;
	Node.x =x;
	Node.y =y;
	Q.push(Node);
	inq[x][y]=true;
	while(!Q.empty()){
		node top = Q.front();
		Q.pop();
		for(int i=0;i<4;i++){
			int newx = top.x + X[i];
			int newy = top.y + Y[i];
			if(judge(newx,newy)){
				Node.x = newx;
				Node.y = newy;
				Q.push(Node);
				inq[newx][newy]=true;
			}
		}
		
	}
} 

int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			scanf("%d",&matrix[i][j]);
		}
	}
	int ans;//存放块数
	for(int x=0;x<n;x++){
		for(int y=0;y<m;y++){
			if(matrix[x][y]==1&&inq[x][y]==false){
				ans++;
				BFS(x,y);
			}
		}
	}
	 printf("%d",ans);
	 return 0;
}

这里给出DFS的实现方法:
DFS:

#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;
const int maxn =30;
int matrix[maxn][maxn];
bool inq[maxn][maxn]={false};
int n,m;


void DFS(int x,int y){
	//如果点超出边界或者碰到零对象则看作是死胡同返回 
	if(x>=n||x<0||y>=m||y<0) return;
	if(matrix[x][y]==0||inq[x][y]==true) return;
	//岔道口 
	inq[x][y]=true;
	DFS(x+1,y);
	DFS(x-1,y);
	DFS(x,y+1);
	DFS(x,y-1);
} 

int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			scanf("%d",&matrix[i][j]);
		}
	}
	int ans;//存放块数
	for(int x=0;x<n;x++){
		for(int y=0;y<m;y++){
			if(matrix[x][y]==1&&inq[x][y]==false){
				ans++;
				DFS(x,y);
			}
		}
	}
	 printf("%d",ans);
	 return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值