DFS-BFS

一、基础

图的存储方式
邻接矩阵
多条边 邻接表
有向边 邻接矩阵不对称

二、dfs遍历结点

每次选择一个一个没有访问过的结点然后dfs,直到每一个点都被访问
非递归:用栈,可以用STL写

三、bfs

分层,
1、访问顶点v
2、访问与顶点v距离k且没有被访问过的顶点
3、如果搞完了还有顶点没访问,从任一个没访过的点开始重新bfs
用队列(STL)实现,一个数指头一个指尾,每次从头取一个点,然后遍历它的下一级点,加到tail后面,终止:head=tail

例题:

1、flood-fill问题 - 数陆地块11994

每次都找到一个没遍历过的点,对它上下左右遍历,直到把它周围的路地块全部遍历一遍,每次找到这样的点可以cnt++
在这里插入图片描述

#include<iostream>
using namespace std;
int n,m,ans = 0;
int a[505][505] = {0};
bool vis[505][505] = {0};
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};

void dfs(int x,int y){
	for(int i=0;i<4;i++){
		if(x+dx[i]>n||x+dx[i]<1||y+dy[i]>m||y+dy[i]<1) continue;
		if(vis[x+dx[i]][y+dy[i]]==0 && a[x+dx[i]][y+dy[i]]==0) {
			vis[x+dx[i]][y+dy[i]] = true;
			dfs(x+dx[i],y+dy[i]);
		}
	}
	return ;
}


int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>a[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(vis[i][j]==0 && a[i][j]==0) {
				vis[i][j] = true;
				dfs(i,j);
				ans ++;	
			}
		}
	cout<<ans<<endl;
	return 0;
} 

2、寻路问题:方格上二人都到同一个点14175

选择酒吧:可以选的每一个点都作为目标点来一次,ans取min
本来是最短路问题,但是每走一条边代价相同,所以可以用bfs实现

在这里插入图片描述

#include<iostream>
using namespace std;
const int N = 1005;
struct Node{
	int x,y;
	int dist;
};
Node a[N*N],a1[N*N],a2[N*N],h,s;
char c[N][N]; 
int n,m,barr = 0,head,tail,tail1,ans1,ans2,ans = 2*N*N;
Node bar[N*N];
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
bool vis[N][N];

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			cin>>c[i][j];
			if(c[i][j]=='#') continue;
			if(c[i][j]=='B') {
				bar[++barr].x = i;
				bar[barr].y = j; 
			}
			if(c[i][j]=='H') {
				h.x = i;
				h.y = j;
			}
			if(c[i][j]=='S') {
				s.x = i;
				s.y = j;
			}
		}
	for(int i=0;i<=m+1;i++) c[0][i] =  c[n+1][i] = '#';
	for(int i=0;i<=n+1;i++) c[i][0] =  c[i][m+1] = '#';
//	for(int i=0;i<=n+1;i++) {
//			for(int j=0;j<=m+1;j++) cout<<c[i][j]<<" ";
//			cout<<endl;
//	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			vis[i][j] = false;
	head = 0;tail = 1;
	a1[0].x = h.x ;
	a1[0].y = h.y ;
	a1[0].dist = 0;
	vis[h.x][h.y] = true;
	while(head!=tail){
		Node u;
		u.x = a1[head].x ;
		u.y = a1[head].y ;
		u.dist = a1[head].dist ;
		for(int i=0;i<4;i++){
			if(c[u.x+dx[i]][u.y+dy[i]]!='#' && vis[u.x+dx[i]][u.y+dy[i]]==0) {
				a1[tail].x = u.x+dx[i];	
				a1[tail].y = u.y+dy[i];	
				a1[tail].dist = u.dist +1;
				vis[u.x+dx[i]][u.y+dy[i]] = true;
				tail++;
			}
		}
		head++; 
	}
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			vis[i][j] = false;
	tail1 = tail;
	head = 0; tail = 1;
	a2[0].x = s.x ;
	a2[0].y = s.y ;
	a2[0].dist = 0;
	vis[s.x][s.y] = true;
	while(head!=tail){
		Node u;
		u.x = a2[head].x ;
		u.y = a2[head].y ;
		u.dist = a2[head].dist ;
		for(int i=0;i<4;i++){
			if(c[u.x+dx[i]][u.y+dy[i]]!='#' && vis[u.x+dx[i]][u.y+dy[i]]==0) {
				a2[tail].x = u.x+dx[i];	
				a2[tail].y = u.y+dy[i];	
				a2[tail].dist = u.dist +1;
				vis[u.x+dx[i]][u.y+dy[i]] = true;
				tail++;
			}
		}
		head++; 
	}
	
	for(int i=1;i<=barr;i++){
		ans1 = N*N;
		ans2 = N*N;
		for(int j=0;j<=tail1;j++){
			if(bar[i].x == a1[j].x && bar[i].y == a1[j].y ) {
				ans1 = a1[j].dist ;
				break;
			}
		}
		if(ans1==N*N) continue;
		for(int j=0;j<=tail;j++){
			if(bar[i].x == a2[j].x && bar[i].y == a2[j].y ) {
				ans2 = a2[j].dist ;
				break;
			}
		}
		if(ans>ans1+ans2) ans = ans1 + ans2;
//		cout<<ans1<<" "<<ans2<<endl;
	}
	cout<<ans<<endl;
	return 0;
} 

改了好久!!首先T掉是因为对每个B都搜了两次,铁定超时;第二是没加检验ans1的一步,T了一个点,加上后过了。写了struct的node,美观很多,很多东西都用node类型,好写很多!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值