DFS和BFS谁更合适呢

目前结论

目前结论就是: 极大连通子图用dfs好点,还有棋盘问题,八皇后,搜索全部的解 ,求最远路径,如156:LETTERS

求最短路径bfs合适点,遇到的第一个解就是最优解

BFS是向(能走的方向拓展),第一次拓展到达终点时,这条路就是起点到终点的最短路径
DFS是从起始点出发往深处走,能走多深走多深,可以分开每一条道路并比较所有的路的情况
BFS虽然很快找到离终点最近的路,但也许题目所求的未必是直接这条路,而是满足条件的结果,比如 鸣人与佐助那题,虽然找到到终点最短的路,但未必是查克拉消耗最少的路。也就是,题目要求的不一定是路径最短,而是另一个量的最值。

156:LETTERS(dfs求最长路径)

156:LETTERS
一开始读错了题意,以为像算水坑个数(求最大连通子图的个数)那道题,求一个水坑的水洼数目。
正解是:一条路上能走过的不同字母
这道题DFS就很适用了,求一条路上的情况
DFS就可以比较不同的道路上的情况
但据说DFS能解决的BFS都可以,但我BFS还没解出来(4分

 #include<bits/stdc++.h>
using namespace std;
char a[25][25];
int vis[26];//a[0]代表A被到达过几次 
int viss[25][25];
//int dx[8]={1,-1,0,0,-1,1,-1,1};
//int dy[8]={0,0,-1,1,-1,-1,1,1};
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
	int m,n;
bool inside(int cx,int cy){
	return (cx>=0&&cx<m&&cy>=0&&cy<n);
}
void init(){
		memset(vis,0,sizeof(vis));
		memset(viss,0,sizeof(viss));
}

int maxx=0;
void dfs(int x,int y,int step){
//	cnt++;
	maxx=max(step,maxx);
	for(int i=0;i<4;i++){
		int cx=x+dx[i];
		int cy=y+dy[i];
		if(inside(cx,cy)&&!viss[cx][cy]&&!vis[a[cx][cy]-'A']){
			viss[cx][cy]=1;
				vis[a[cx][cy]-'A']++;
			dfs(cx,cy,step+1);
				viss[cx][cy]=0;
				vis[a[cx][cy]-'A']--;
		}
	} 
}
int main(){//同一个字母不能访问两次 
	ios_base::sync_with_stdio(0);

	cin>>m>>n;
	for(int i=0;i<m;i++){
		for(int j =0;j<n;j++){
			cin>>a[i][j];
		}
	} 
	init();
	vis[a[0][0]-'A']=1;
	viss[0][0]=1;
	dfs(0,0,1);

	cout<<maxx;
    return 0;
} 

BFS(只有4分)how to do?

 #include<bits/stdc++.h>
using namespace std;
char a[25][25];
int vis[26];//a[0]代表A被到达过几次 
int viss[25][25];
//int dx[8]={1,-1,0,0,-1,1,-1,1};
//int dy[8]={0,0,-1,1,-1,-1,1,1};
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
	int m,n;
bool inside(int cx,int cy){
	return (cx>=0&&cx<m&&cy>=0&&cy<n);
}
void init(){
		memset(vis,0,sizeof(vis));
}
struct node{
	int x;
	int y;
	node(int xx,int yy):x(xx),y(yy){}
}; 
queue<node> Q;
int cnt=0;
void bfs(){
	while(!Q.empty()){
		node p=Q.front();Q.pop();
		cnt++;
		int x=p.x;
		int y=p.y;
		for(int i=0;i<4;i++){
			int cx=x+dx[i];
			int cy=y+dy[i];
			char ch=a[cx][cy];
			if(inside(cx,cy)&&!viss[cx][cy]&&vis[ch-'A']==0){
				Q.push(node(cx,cy));
				vis[ch-'A']=1;
				viss[cx][cy]=1;
				bfs();//加上这条五分 
			}
		}
	} 
}
int main(){//同一个字母不能访问两次 
	ios_base::sync_with_stdio(0);

	cin>>m>>n;
	for(int i=0;i<m;i++){
		for(int j =0;j<n;j++){
			cin>>a[i][j];
		}
	} 
	init();
	Q.push(node(0,0));
	vis[a[0][0]-'A']=1;
	viss[0][0]=1;
	bfs();
	cout<<cnt;
    return 0;
} 

166:The Castle城堡问题(联通子集个数、大小)

传送门
求极大连通子图,
据说dfs能解决的bfs都能解,那这题用bfs怎么解呢?

 #include<bits/stdc++.h>
using namespace std;
int a[55][55]; 
int vis[55][55]; 
int m,n;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int maxx=-1;
bool inside(int cx,int cy){
	return (cx>=0&&cx<m&&cy>=0&&cy<n);
}
void init(){
	memset(vis,0,sizeof(vis));
		memset(a,0,sizeof(a));
}
int room;//房间数
int space;//最大的房间多大,比较每个房间的space取max 
void dfs(int x,int y){
	if(vis[x][y])return;
	else{
		space++; 
		vis[x][y]=1;
	}
	int state=a[x][y];
	int cx=-1;
	int cy=-1;
	if(!(state&1)){//西面没墙 
		if(inside(x,y-1)&&!vis[x][y-1]){
					cx=x;
					cy=y-1;
			dfs(cx,cy);
		}
	}
		if(!(state&2)){//北面没墙 

		if(inside(x-1,y)&&!vis[x-1][y]){
					cx=x-1;
					cy=y;
			dfs(cx,cy);
		}
	}
		if(!(state&4)){//东面没墙 
		if(inside(x,y+1)&&!vis[x][y+1]){
					cx=x;
					cy=y+1;		
			dfs(cx,cy);
		}
	}
		if(!(state&8)){//南面没墙 
		if(inside(x+1,y)&&!vis[x+1][y]){
					cx=x+1;
					cy=y;
			dfs(cx,cy);
		}
	}
	if(cx==-1&&cy==-1){
		maxx=max(maxx,space);
		return ;
	}
}
int main(){//同一个字母不能访问两次 
	ios_base::sync_with_stdio(0);
		cin>>m>>n;
		init();	
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				cin>>a[i][j];
	}
}
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				if(!vis[i][j]){
					space=0; 
					room++;//存放房间数 
					dfs(i,j);

					
				}
	}
}
cout<<room<<endl;
cout<<maxx<<endl;	
    return 0;
} 

又重新做了一遍

#include<iostream>
#include <algorithm>
using namespace std;
const int N=55;
int m,n;
int vis[N][N];
int a[N][N];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
bool inside(int x,int y){
	if(x>=0&&x<m&&y>=0&&y<n)return true;
	else return false;
}
int maxx=-1;
int step; 
void dfs(int x,int y){
	maxx=max(maxx,step);
		int v=a[x][y];
		if(!(v&1)&&inside(x,y-1)&&!vis[x][y-1]){
			vis[x][y-1]=1;
			step++;
			dfs(x,y-1);//下一条路不能走这一点了 
		}
		if(!(v&2)&&inside(x-1,y)&&!vis[x-1][y]){
			vis[x-1][y]=1;
			step++;
			dfs(x-1,y);
		}
		if(!(v&4)&&inside(x,y+1)&&!vis[x][y+1]){
			vis[x][y+1]=1;
			step++;
			dfs(x,y+1); 
		}
		if(!(v&8)&&inside(x+1,y)&&!vis[x+1][y]){
			vis[x+1][y]=1;
			step++;
			dfs(x+1,y);
		}
	
}
int main() {//56
	cin>>m>>n;
	int cnt=0;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			cin>>a[i][j];
		}
	}
		for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			if(!vis[i][j]) {
				vis[i][j]=1;
				step=1;//step,一个房间的大小
				cnt++;//房间数量 
				dfs(i,j);
			}
		}
	}
 	cout<<cnt<<endl<<maxx; 
    return 0;
}
//求最大联通子集,其中所有元素不一定能一条路踏遍2,一笔画 

1388:Lake Counting(联通子集个数)

#include<iostream>
#include <algorithm>
using namespace std;
const int N=105;
int m,n;
int vis[N][N];
char a[N][N];
int dx[8]={1,-1,0,0,1,1,-1,-1};
int dy[8]={0,0,1,-1,1,-1,-1,1};
bool inside(int x,int y){
	if(x>=0&&x<m&&y>=0&&y<n)return true;
	else return false;
}

void dfs(int x,int y){
	for(int i=0;i<8;i++){
		int cx=x+dx[i];
		int cy=y+dy[i];
		if(inside(cx,cy)&&!vis[cx][cy]&&a[cx][cy]=='W'){
			vis[cx][cy]=1;
			dfs(cx,cy); 
		}
	}
	
}
int main() {//36
	cin>>m>>n;
	int cnt=0;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			cin>>a[i][j];
		}
	}
		for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			if(a[i][j]=='W'&&!vis[i][j]) {
				vis[i][j]=1;
//				step=1;//step,一个联通子集的大小
				cnt++;//联通子集数量 
				dfs(i,j);
			}
		}
	}
 	cout<<cnt; 
    return 0;
}
//求最大联通子集,其中所有元素不一定能一条路踏遍2,一笔画 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值