最短路BFS、多源BFS、最小步数

迷宫问题

1076. 迷宫问题 - AcWing

        从左上角到右下角的最短路径,输出最短路径 

        BFS入队时记录(nx,ny)的上一点(x,y), 输出路径时从终点开始回溯,到起点停止 

#include<bits/stdc++.h>
using namespace std;
#define fast(); ios::sync_with_stdio(false);cin,tie(0),cout.tie(0);
typedef long long ll;
typedef pair<int,int> PII;
const int N=1e3+5;
int n;
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
int w[N][N];
int vis[N][N];
PII path[N][N];
void bfs(int x,int y){
	queue<PII> q;
	q.push({0,0});
	vis[0][0]=true;
	while(!q.empty()){
		PII t=q.front();q.pop();
		int x=t.first,y=t.second;
		if(x==n-1&&y==n-1) break;
		for(int i=0;i<4;i++){
			int nx=x+dx[i],ny=y+dy[i];
			if(nx<0||ny<0||nx>=n||ny>=n) continue;
			if(w[nx][ny]==1) continue;
			if(vis[nx][ny]) continue;
			vis[nx][ny]=true;
			q.push({nx,ny});
			path[nx][ny]={x,y};//记录路径 
		}
	}
} 
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cin>>w[i][j];
		}
	}
	bfs(0,0);
	//输出路径,从终点开始回溯,到起点停止 
	vector<PII> vc;
	int x=n-1,y=n-1;
	vc.push_back({x,y});
	do{
		PII t=path[x][y];
		x=t.first,y=t.second;
		vc.push_back({x,y});
	}while(x!=0||y!=0);
	reverse(vc.begin(),vc.end());
	for(auto t:vc){
		cout<<t.first<<" "<<t.second<<endl;
	}
	
} 

武士风度的牛

188. 武士风度的牛 - AcWing题库

        马走日,从起点到终点的最小步数

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;

int n,m;
const int N=1e3+5;
char g[N][N];
int dx[]={2,-2,2,-2,1,1,-1,-1};
int dy[]={1,1,-1,-1,2,-2,2,-2};
PII st,ed;
bool vis[N][N];
int dis[N][N];
void bfs(){
	queue<PII> q;
	q.push({st.first,st.second});
	vis[st.first][st.second]=true;
	while(!q.empty()){
		PII t=q.front();q.pop();
		int x=t.first,y=t.second;
		if(x==ed.first&&y==ed.second) break;
		for(int i=0;i<8;i++){
			int nx=x+dx[i],ny=y+dy[i];
			if(nx<1||ny<1||nx>n||ny>m) continue;
			if(g[nx][ny]=='*') continue;
			if(vis[nx][ny]) continue;
			vis[nx][ny]=true;
			q.push({nx,ny});
			dis[nx][ny]=dis[x][y]+1;//记录步数 
		}
	}
}
int main(){
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>g[i]+1;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(g[i][j]=='K') st={i,j};
			if(g[i][j]=='H') ed={i,j};
		}
	}
	bfs(); 
	cout<<dis[ed.first][ed.second];
} 

矩阵距离(多源BFS)

173. 矩阵距离 - AcWing题库

        01矩阵,每个0距离最近的1的距离

        将所有1入队进行BFS,记录搜到的每个点的距离,即0到最近的1的距离

注意:初始入队时,将每个1的vis标记为true,搜索时只入队0

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int n,m;
const int N=1e3+5;
char g[N][N];
int dx[]={0,1,-1,0};
int dy[]={1,0,0,-1};
PII st,ed;
bool vis[N][N];
int dis[N][N];
void bfs(){
	queue<PII> q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(g[i][j]=='1'){
				q.push({i,j});
				vis[i][j]=true;
			}
		}
	}
	while(!q.empty()){
		PII t=q.front();q.pop();
		int x=t.first,y=t.second;
		for(int i=0;i<4;i++){
			int nx=x+dx[i],ny=y+dy[i];
			if(nx<1||ny<1||nx>n||ny>m) continue;
			if(vis[nx][ny]) continue;
			vis[nx][ny]=true;
			q.push({nx,ny});
			dis[nx][ny]=dis[x][y]+1;
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>g[i]+1;
	}
	bfs();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cout<<dis[i][j]<<" ";
		}
		cout<<endl;
	}
} 

魔板(最小步数)

1107. 魔板 - AcWing题库

        每个字符串代表一个状态,给定初态和终态,字符串可以进行指定变换,求初态到终态的最小变换次数,且输出变换次序

#include<iostream>
#include<queue>
#include<map>
#include<algorithm>
#include<unordered_map>
using namespace std;
string res="";
unordered_map<string,int> dist;
unordered_map<string,pair<char,string> > pre;
char g[2][4];
void set(string s){
	for(int i=0;i<4;i++)
		g[0][i]=s[i];
	for(int i=3,j=4;i>=0;i--,j++)
		g[1][i]=s[j];
}
string get(){
	string s="";
	for(int i=0;i<4;i++)
		s+=g[0][i];
	for(int i=3;i>=0;i--)
		s+=g[1][i];
	return s;
}
string m1(string s){
	set(s);
	for(int i=0;i<4;i++) swap(g[0][i],g[1][i]);
	return get();
}
string m2(string s){
	set(s);
	char a,b;
	a=g[0][3],b=g[1][3];
	for(int i=2;i>=0;i--)
		g[0][i+1]=g[0][i],g[1][i+1]=g[1][i];
	g[0][0]=a,g[1][0]=b;
	return get();
}
string m3(string s){
	set(s);
	char a=g[0][1];
	g[0][1]=g[1][1];
	g[1][1]=g[1][2];
	g[1][2]=g[0][2];
	g[0][2]=a;
	return get();
}
void bfs(string start,string end){
	if(start==end) return;
	queue<string> q;
	q.push(start);
	dist[start]=0;
	while(!q.empty()){
		string t=q.front();q.pop();
		if(t==end) return;
		string s[3];
		s[0]=m1(t);
		s[1]=m2(t);
		s[2]=m3(t);
		for(int i=0;i<3;i++){
			string str=s[i];
			if(dist.count(str)==0){
				dist[str]=dist[t]+1;
				pre[str]={char(i+'A'),t};
				q.push(str);
			}
		}
	}
}
int main(){
	string start="12345678",end="";
	for(int i=1;i<=8;i++){
		char c;cin>>c;
		end+=c;
	}
	bfs(start,end);
	cout<<dist[end]<<endl;
	while(end!=start){
		res+=pre[end].first;
		end=pre[end].second;
	}
	reverse(res.begin(),res.end());
	if(res.size()) cout<<res;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vic.GoodLuck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值