01BFS经典题型
未完,待更。。。
01bfs又称双端队列bfs,本质上是Dijkstra算法,所以应该用到松弛数组dis,而不应该用判重数组,即使有的题目能通过判重通过也最好不好用
CF590C Three States
思路:
01bfs,然后枚举交点,
AC代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof a)
#define ll long long
using namespace std;
const int N = 1010;
char s[N][N];
int dis[N][N][5],n,m;
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1};
struct node
{
int x,y;
};
void bfs(char x)
{
// mem(dis,0x3f);
//mem(vis,0);
deque<node> q;
//将每个点x作为起点放入队列里面,跑多源bfs
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(s[i][j]==x)
{
q.push_front({i,j});
// vis[i][j]=1;
dis[i][j][x-'0']=0;
}
while(q.size())
{
auto tmp=q.front();
q.pop_front();
for(int i=0; i<4; i++)
{
int nx=tmp.x+dx[i];
int ny=tmp.y+dy[i];
if(nx<0||ny<0||nx>=n||ny>=m||s[nx][ny]=='#') continue;
if(dis[nx][ny][x-'0']==INF&&s[nx][ny]!='#')
{
int w=(s[nx][ny]=='.');
dis[nx][ny][x-'0']=dis[tmp.x][tmp.y][x-'0']+w;
if(w==1) q.push_back({nx,ny});
else q.push_front({nx,ny});
}
}
}
}
int main()
{
mem(dis,0x3f);
cin>>n>>m;
for(int i=0; i<n; i++) scanf("%s",s[i]);
bfs('1'),bfs('2'),bfs('3');
ll ans=INF;
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++ )
{
if(s[i][j]!='#')
{
ll tmp=0;
for(int k=1; k<=3; k++)
{
//if(i==7&&j==5) printf("dis[%d][%d][%d]=%d\n",i,j,k,dis[i][j][k]);
tmp+=dis[i][j][k];
}
if(s[i][j]=='.') tmp-=2;
ans=min(ans,tmp);
}
}
}
if(ans>=3e6) puts("-1");
else printf("%lld\n",ans);
return 0;
}
cf Jailbreak
思路
我们把犯人1标记为1,犯人2标记为2,在地图的外围标记一圈2.这道题等价于1,2,3三个区域走到同一点,花费最小。于是和上一道题一样了
AC代码
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int N = 1010;
char mp[N][N];
int n,m;
int dx[10]={-1,1,0,0};
int dy[10]={0,0,-1,1};
bool vis[N][N];
int dis[N][N][5];
struct node
{
int x,y;
};
void bfs(int x)
{
mem(vis,0);
deque<node> q;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(mp[i][j]==x+'0')
{
q.push_back({i,j});
vis[i][j]=1;
dis[i][j][x]=0;
}
}
}
while(q.size())
{
auto tmp = q.front();
q.pop_front();
for(int i=0; i<4; i++)
{
int nx=tmp.x+dx[i];
int ny=tmp.y+dy[i];
if(nx<0||ny<0||nx>n||ny>m||vis[nx][ny]) continue;
if(mp[nx][ny]!='*')
{
int w = (mp[nx][ny]=='#');
dis[nx][ny][x]=dis[tmp.x][tmp.y][x]+w;
vis[nx][ny]=1;
if(w)
{
q.push_back({nx,ny});
}
else q.push_front({nx,ny});
}
}
}
// puts("debug");
return ;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
int cnt=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
cin>>mp[i][j];
if(mp[i][j]=='$') mp[i][j]=++cnt+'0';
}
}
//给外围加上一圈
for(int j=0; j<=m+1; j++)
{
mp[0][j]='3';
mp[n+1][j]='3';
}
for(int i=0; i<=n+1; i++)
{
mp[i][0]='3';
mp[i][m+1]='3';
}
// mem(vis,0);
mem(dis,0x3f);
n++,m++;
bfs(1),bfs(2),bfs(3);
ll ans=INF;
for(int i=0; i<=n; i++)
{
for(int j=0; j<=m; j++)
{
ll tmp=0;
if(mp[i][j]!='*')
{
tmp+=1ll*(1ll*dis[i][j][1]+dis[i][j][2]+dis[i][j][3]);
if(mp[i][j]=='#') tmp-=2;
ans=min(ans,tmp);
}
}
}
// cout<<ans<<endl;
printf("%d\n",ans);
}
return 0;
}
UVA11573 Ocean Currents
思路
基础的01bfs,注意这道题一个点可能多次入队,所以应该用dis数组进行松弛操作
AC代码
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
const int N = 1010;
char mp[N][N];
int n,m;
int dx[10]={-1,-1,0,1,1,1,0,-1};
int dy[10]={0,1,1,1,0,-1,-1,-1};
int dis[N][N];
bool vis[N][N];
struct node
{
int x,y;
};
int bfs(int x1,int y1,int x2,int y2)
{
mem(vis,0);
mem(dis,0x3f);
deque<node> q;
q.push_back({x1,y1});
vis[x1][y1]=1;
dis[x1][y1]=0;
while(q.size())
{
auto tmp = q.front();
q.pop_front();
if(tmp.x==x2&&tmp.y==y2) return dis[x2][y2];
for(int i=0; i<8; i++)
{
int nx=tmp.x+dx[i];
int ny=tmp.y+dy[i];
if(nx<1||ny<1||nx>n||ny>m) continue;
if(vis[nx][ny]) continue;
int w = (mp[tmp.x][tmp.y]!=i+'0');
if(dis[nx][ny]>dis[tmp.x][tmp.y]+w)
{
dis[nx][ny]=dis[tmp.x][tmp.y]+w;
if(w) q.push_back({nx,ny});
else
{
q.push_front({nx,ny});
// puts("debug");
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
{
scanf("%s",mp[i]+1);
}
int q;
cin>>q;
while(q--)
{
int x1,y1,x2,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
int ans=bfs(x1,y1,x2,y2);
printf("%d\n",ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话