10.3

BFS
题目列表
A
dfs求连通性
把所有1的点能联通的点,全部消掉,计数,依次
上码

#include <bits/stdc++.h>
using namespace std;////23058720
const int N=1010;
int mp[N][N],n,m;
int dx[]={0,0,1,-1,1,-1,1,-1};
int dy[]={1,-1,0,0,1,1,-1,-1};
void dfs(int x,int y){
	for(int i=0;i<8;i++){
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx<1||xx>n||yy<1||y>m)continue;
		if(mp[xx][yy]==1){
			mp[xx][yy]=0;
			dfs(xx,yy);
		}
			
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char c;
			cin>>c;
			if(c=='w')mp[i][j]=1;
		}
	}
	int num=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(mp[i][j]){
				dfs(i,j);
				num++;
			}
		}
	}
	cout<<num<<endl;
	return 0;
}

B
一道网格图最短路问题,显然只搜到一条x-y的最短路径就可以了,不用搜出所有路径,选用bfs

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
char mp[N][N];
int n,m,dis[N][N];
int dx[] ={2, 2, 1, 1, -1, -1, -2, -2};
int dy[] ={1, -1, 2, -2, -2, 2, 1, -1};
int sx,sy,ex,ey;
void bfs(){
	queue<pair<int ,int > >q;
	dis[sx][sy]=0;
	q.push({sx,sy});
	while(!q.empty()){
		int x=q.front().first;
		int y=q.front().second;
		if(mp[x][y]=='H'){
			cout<<dis[x][y]<<endl;
			return;
		}
		q.pop();
		for(int i=0;i<8;i++){
			int xx=x+dx[i];
			int yy=y+dy[i];
			if(xx<1||xx>n||yy<1||yy>m||mp[xx][yy]=='*'||dis[xx][yy]!=-1)continue;
			dis[xx][yy]=dis[x][y]+1;
			q.push({xx,yy});
		}
	}
}
int main(){
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>mp[i][j];
			if(mp[i][j]=='K'){
				sx=i,sy=j;
			}
			if(mp[i][j]=='H'){
				ex=i,ey=j;
			}
			dis[i][j]=-1;
		}
	}
	bfs();
	
	return 0;
}

C
求每个0到离它最近的1的曼哈顿距离
把曼哈顿距离转化为上下左右去扩展
第一种办法:对于每一0去跑bfs,每次只能得到一个点的答案,bfs时间复杂度为O(nn),显然会超时
正解:对于每一个1去跑bfs,跑一次得到的点的答案为1-n
n,时间复杂度降低
代码

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
char mp[N][N];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int dis[N][N];
void bfs(){
	memset(dis,-1,sizeof dis);
	queue<pair<int ,int > >q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(mp[i][j]=='1'){
				q.push({i,j});
				dis[i][j]=0;
			}
		}
	}
	while(!q.empty()){
		int x=q.front().first;
		int y=q.front().second;
		q.pop();
		for(int i=0;i<4;i++){
			int xx=x+dx[i];
			int yy=y+dy[i];
			if(xx<1||xx>n||yy<1||yy>m||dis[xx][yy]!=-1)continue;
			dis[xx][yy]=dis[x][y]+1;
			q.push({xx,yy});
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>mp[i][j];
		}
	}
	bfs();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cout<<dis[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

D
上难度了
对于A B C三种操作
A:倒序
B:设原字符串为s(0,n-1),s0=s3,s1=s0,s2=s1,s3=s2,s4=s5,s5=s6,s6=s7,s7=s4,
C:s1=s6,s2=s1,s5=s2,s6=s5
用一个哈希表标记,防止重复
对于每一种状态跑bfs,搜出他的三个状态,如果相等,直接退出,bfs(确保是最短的的)
代码

#include <bits/stdc++.h>
using namespace std;
string a;
unordered_map<string ,string> mp;
queue<string>q;
void A(string s){
	string ss=s;
	for(int i=0;i<4;i++){
		char x1=s[i];
		s[i]=s[7-i];
		s[7-i]=x1;
	}
	if(mp.count(s)==0){
		q.push(s);
		mp[s]=mp[ss]+'A';
	}
}

void B(string s){
	string ss=s;
	s[0]=ss[3],s[1]=ss[0],s[2]=ss[1],s[3]=ss[2],s[4]=ss[5],s[5]=ss[6],s[6]=ss[7],s[7]=ss[4];
	if(mp.count(s)==0){
		q.push(s);
		mp[s]=mp[ss]+'B';
	}
}
void C(string s){
	string ss=s;
	s[1]=ss[6],s[2]=ss[1],s[5]=ss[2],s[6]=ss[5];
	if(mp.count(s)==0){
		q.push(s);
		mp[s]=mp[ss]+'C';
	}
}
void bfs(){
	q.push("12345678");
	mp["12345678"]="";
	while(!q.empty()){
		string x=q.front();
		q.pop();
		A(x),B(x),C(x);
		if(mp.count(a)!=0){
			cout<<mp[a].size()<<endl<<mp[a]<<endl;
			return;
		}
	}
}
int main(){
	for(int i=1;i<=8;i++){
		char c;
		cin>>c;
		a+=c;
		getchar();
	}
	bfs();
	return 0;
}

E
远古老题
双向广搜
例如在已知终点和起点的情况下求是否能到达,需要走多远路。那既然已知终点,为何不从终点同时开始进行搜索,看看是否能在中间相遇。
方法:分成两个队列。正向 BFS 和逆向 BFS 的队列分开。让子状态少的 BFS 先扩展下一层,另一个子状态多的 BFS 后扩展,任一队列的状态扩展完后就结束,可以减少搜索的总状态数,尽快相遇。双向广搜在扩展队列时也需要处理去重问题。把状态入队列的时候,先判断这个状态是否曾经入队,如果重复了,就丢弃。

F
bfs/dfs求联通性板子

剪枝(迭代加深,最优性剪枝,记忆化,可行性剪枝,搜索顺序),搜索树
dfs 指数,排列,组合

posted @ 2025-12-13 11:35  kksc111  阅读(11)  评论(0)    收藏  举报