2024算法基础公选课练习七(BFS1)

server/2024/11/28 7:18:04/

一、前言

还是偏基础的bfs,但是有几个题不是很好写

二、题目总览

三、具体题目

3.1 问题 A: 数据结构-队列-奇怪的电梯

我的代码

可以看成求一维平面的bfs最短路

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e5+5,M = 1e6+5,INF = 0x3f3f3f3f;
std::vector<int> a(N,0);
std::vector<bool> vis(N,false);int n,st,ed;void bfs(){std::queue<pii> q;vis[st] = true;pii p;p.first = st,p.second = 0;q.emplace(p);while(!q.empty()){auto t = q.front();q.pop();if(t.first==ed){std::cout << t.second << '\n';return;}pii t1,t2;t1.first = t.first+a[t.first];t1.second = t.second+1;if(t1.first<=n&&!vis[t1.first]){vis[t1.first] = true;q.emplace(t1);}t2.first = t.first-a[t.first];t2.second = t.second+1;if(t2.first>=1&&!vis[t2.first]){vis[t2.first] = true;q.emplace(t2);}}std::cout << "-1\n";
}void solve(){std::cin >> n >> st >> ed;for(int i = 1;i<=n;++i) std::cin >> a[i];bfs();}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.2 问题 B: 连通块

我的代码

找全是1的联通块个数,直接枚举每个点bfs(当前未访问过的点)即可

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e2+5,M = 1e6+5,INF = 0x3f3f3f3f;
int n,m;
int g[N][N];
bool vis[N][N];
int ans;
using node = std::array<int,3>;
int dx[] = {0,0,-1,1};
int dy[] = {-1,1,0,0};
void bfs(int sx,int sy){std::queue<node> q;node t;t[0] = sx,t[1] = sy,t[2] = 0;q.emplace(t);vis[sx][sy] = true;++ans;while(!q.empty()){auto t = q.front();q.pop();for(int i = 0;i<4;++i){int u = t[0]+dx[i],v = t[1]+dy[i];if(u<1||u>n||v<1||v>m||vis[u][v]||g[u][v]==0) continue;node t1;vis[u][v] = true;t1[0] = u,t1[1] = v,t1[2] = t[2]+1;q.emplace(t1);}}
}
void solve(){std::cin >> n >> m;for(int i = 1;i<=n;++i){for(int j = 1;j<=m;++j){std::cin >> g[i][j];}}for(int i = 1;i<=n;++i){for(int j = 1;j<=m;++j){if(!vis[i][j]&&g[i][j]==1){bfs(i,j);}}}std::cout << ans << '\n';
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.3 问题 C: 广搜——营救

我的代码

用char读图,不能用int,后续就是简单的求二维平面的bfs最短路

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e3+5,M = 1e6+5,INF = 0x3f3f3f3f;
int n;
char g[N][N];
bool vis[N][N];
int sx,sy,ex,ey;
using node = std::array<int,3>;
int dx[] = {0,0,-1,1};
int dy[] = {-1,1,0,0};void bfs(){std::queue<node> q;node tt;tt[0] = sx,tt[1] = sy,tt[2] = 0;q.emplace(tt);vis[sx][sy] = true;while(!q.empty()){auto t = q.front();q.pop();if(t[0]==ex&&t[1]==ey){std::cout << t[2] << '\n';return;}for(int i = 0;i<4;++i){int u = t[0]+dx[i],v = t[1]+dy[i];if(u<1||u>n||v<1||v>n||vis[u][v]||g[u][v]=='1') continue;vis[u][v] = true;node t1;t1[0] = u,t1[1] = v,t1[2] = t[2]+1;q.emplace(t1);}}
}
void solve(){std::cin >> n;for(int i = 1;i<=n;++i){for(int j = 1;j<=n;++j){std::cin >> g[i][j];}}std::cin >> sx >> sy >> ex >> ey;bfs();
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.4 问题 D: 迷宫的最短路径

我的代码

注意输出不要漏单词或者空格,其他没啥好说的

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e3+5,M = 1e6+5,INF = 0x3f3f3f3f;
int n,m;
char g[N][N];
bool vis[N][N];
int sx,sy,ex,ey;
int dx[] = {0,0,-1,1};
int dy[] = {-1,1,0,0};
using node = std::array<int,3>;void bfs(){std::queue<node> q;node tt;tt[0] = sx,tt[1] = sy,tt[2] = 0;q.emplace(tt);vis[sx][sy] = true;while(!q.empty()){auto t = q.front();q.pop();if(t[0]==ex&&t[1]==ey){std::cout << "The min steps are:" << t[2] << "!\n";return;}for(int i = 0;i<4;++i){int u = t[0]+dx[i],v = t[1]+dy[i];if(u<1||u>n||v<1||v>m||vis[u][v]||g[u][v]=='#') continue;vis[u][v] = true;node t1;t1[0] = u,t1[1] = v,t1[2] = t[2]+1;q.emplace(t1);}}std::cout << "sorry!\n";
}void solve(){std::cin >> n >> m;for(int i = 1;i<=n;++i){for(int j = 1;j<=m;++j){std::cin >> g[i][j];if(g[i][j]=='S'){sx=i,sy=j;}else if(g[i][j]=='G'){ex=i,ey=j;}}}bfs();
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.5 问题 E: 象棋中的马之进阶

我的代码

求八方向二维平面最短路的bfs

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e3+5,M = 1e6+5,INF = 0x3f3f3f3f;
bool vis[N][N];
int sx,sy,ex,ey;
int dx[] = {-2,-1,1,2,2,1,-1,-2};
int dy[] = {1,2,2,1,-1,-2,-2,-1};
using node = std::array<int,3>;void bfs(){std::queue<node> q;node tt;tt[0] = sx,tt[1] = sy,tt[2] = 0;q.emplace(tt);vis[sx][sy] = true;while(!q.empty()){auto t = q.front();q.pop();if(t[0]==ex&&t[1]==ey){std::cout << t[2] << '\n';return;}for(int i = 0;i<8;++i){int u = t[0]+dx[i],v = t[1]+dy[i];if(u<1||u>9||v<1||v>10||vis[u][v]) continue;vis[u][v] = true;node t1;t1[0] = u,t1[1] = v,t1[2] = t[2]+1;q.emplace(t1);}}std::cout << 0 << '\n';
}
void solve(){std::cin >> sx >> sy >> ex >> ey;bfs();
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.6 问题 F: 搜索——我的世界

我的代码

求三维空间最短路的bfs

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e2+5,M = 1e6+5,INF = 0x3f3f3f3f;int k,n,m;
char g[N][N][N];
bool vis[N][N][N];
int dx[] = {0,0,-1,1,0,0};
int dy[] = {-1,1,0,0,0,0};
int dz[] = {0,0,0,0,1,-1};
using node = std::array<int,4>;
int sx,sy,sz,ex,ey,ez;
void bfs(){std::queue<node> q;node tt;tt[0] = sz,tt[1] = sx,tt[2] = sy,tt[3] = 0;q.emplace(tt);vis[sx][sy][sz] = true;while(!q.empty()){auto t = q.front();q.pop();if(t[0]==ez&&t[1]==ex&&t[2]==ey){std::cout << t[3] << '\n';return;}for(int i = 0;i<6;++i){int u = t[0]+dz[i],v = t[1]+dx[i],w = t[2]+dy[i];if(u<1||u>k||v<1||v>n||w<1||w>m||vis[u][v][w]||g[u][v][w]=='^') continue;vis[u][v][w] = true;node t1;t1[0] = u,t1[1] = v,t1[2] = w,t1[3] = t[3]+1;q.emplace(t1);}}std::cout << 2333333 << '\n';
}
void solve(){std::cin >> k >> n >> m;for(int i = 1;i<=k;++i){for(int j = 1;j<=n;++j){for(int l = 1;l<=m;++l){std::cin >> g[i][j][l];if(g[i][j][l]=='S'){sx=j,sy=l,sz=i;}else if(g[i][j][l]=='E'){ex=j,ey=l,ez=i;}}}}bfs();
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.7 问题 G: 最小倍数

我的代码

不会爆long long,思路见代码

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e5+5,M = 1e6+5,INF = 0x3f3f3f3f;
i64 n;void bfs(){std::queue<i64> q;q.emplace(1);while(!q.empty()){auto t = q.front();q.pop();if(t%n==0){std::cout << t << '\n';return;}q.emplace(t*10);q.emplace(t*10+1);}
}
void solve(){while(std::cin >> n){if(n==0) break;bfs();}
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.8 问题 H: 01组成的N的倍数

我的代码

会爆long long和unsigned long long,而且用高精度也会超时,时间复杂度卡得有点死,只能用string

#include <bits/stdc++.h> 
using namespace std;
using i64 = long long;
constexpr int N=1e6+5;
struct node{string str;i64 sum;
} now,temp;
queue<node> q;
int vis[N];
int n;
void bfs(){queue<node> q;memset(vis,0,sizeof(vis));now.str="1";now.sum=1%n;vis[now.sum]=1;q.push(now);while(!q.empty()){now=q.front();q.pop();if(now.sum==0){cout << now.str << endl;break;}temp.str=now.str+'0';temp.sum=(now.sum*10)%n;if(vis[temp.sum]==0){vis[temp.sum]=1;q.push(temp);}temp.str=now.str+'1';temp.sum=(now.sum*10+1)%n;if(vis[temp.sum]==0){vis[temp.sum]=1;q.push(temp);}}
}
int main(){while(~scanf("%d",&n)){bfs();}return 0;
}

3.9 问题 I: 新迷宫探险

我的代码

注意多组数据,写法跟前面的求二维平面最短路的bfs一样

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e2+5,M = 1e6+5,INF = 0x3f3f3f3f;
int n;
char g[N][N];
bool vis[N][N];
int sx,sy,ex,ey;
int dx[] = {0,0,-1,1};
int dy[] = {-1,1,0,0};
using node = std::array<int,3>;
void bfs(){std::queue<node> q;node tt;tt[0] = sx,tt[1] = sy,tt[2] = 0;vis[sx][sy] = true;q.emplace(tt);while(!q.empty()){auto t = q.front();q.pop();if(t[0]==ex&&t[1]==ey){std::cout << t[2] << '\n';return;}for(int i = 0;i<4;++i){int u = t[0]+dx[i],v = t[1]+dy[i];if(u<1||u>n||v<1||v>n||vis[u][v]||g[u][v]=='#') continue;vis[u][v] = true;node t1;t1[0] = u,t1[1] = v,t1[2] = t[2]+1;q.emplace(t1);}}std::cout << -1 << '\n';
}
void solve(){while(std::cin >> n){for(int i = 1;i<=n;++i){for(int j = 1;j<=n;++j){std::cin >> g[i][j];}}memset(vis,false,sizeof vis);sx = 1,sy = 1,ex = n,ey = n;bfs();}
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.10 问题 J: 山峰和山谷

我的代码

枚举每个没有访问过的点,bfs看是否能够形成山峰或者山谷

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e3+5,M = 1e6+5,INF = 0x3f3f3f3f;
int n;
int g[N][N];
bool vis[N][N];
int ans1,ans2;
int dx[] = {0,0,-1,1,-1,1,1,-1};
int dy[] = {-1,1,0,0,1,1,-1,-1};using node = std::array<int,2>;void bfs(int i,int j){std::queue<node> q;node tt;tt[0] = i,tt[1] = j;q.emplace(tt);vis[i][j] = true;bool flag1 = false,flag2 = false;int cnt = 1;while(!q.empty()){auto t = q.front();q.pop();for(int i = 0;i<8;++i){int u = t[0]+dx[i],v = t[1]+dy[i];if(u<1||u>n||v<1||v>n||(vis[u][v]&&g[u][v]==g[t[0]][t[1]])) continue;if(g[u][v]<g[t[0]][t[1]]) flag1=true;else if(g[u][v]>g[t[0]][t[1]]) flag2=true;else{++cnt;vis[u][v] = true;node t1;t1[0] = u,t1[1] = v;q.emplace(t1);}}}if(flag1&&flag2) return;if(flag1) ++ans1;else if(flag2) ++ans2;if(cnt==n*n) ++ans1,++ans2;
}
void solve(){std::cin >> n;for(int i = 1;i<=n;++i){for(int j = 1;j<=n;++j){std::cin >> g[i][j];}}for(int i = 1;i<=n;++i){for(int j = 1;j<=n;++j){if(!vis[i][j]){bfs(i,j);}}}std::cout << ans1 << ' ' << ans2 << '\n';
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.11 问题 K: 兔兔之漂亮图

我的代码

这题看代码吧,暂时不知道要怎么说清楚这个思路

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 3e5+5,M = 1e6+5,INF = 0x3f3f3f3f;
constexpr int P = 998244353;i64 power(i64 a, i64 b) {i64 res = 1;for (; b; b /= 2, a = a*a%P) {if (b % 2) {res = res*a%P;}}return res;
}std::vector<std::vector<int>> edges(N,std::vector<int>());
std::vector<int> a(N,0);
int n,m;
i64 ans;
std::queue<int> q;
i64 t = 2;void bfs(){for(int i = 1;i<=n;++i){if(a[i]!=0) continue;a[i] = 1;i64 cnt1 = 1,cnt2 = 0;q.emplace(i);while(!q.empty()){auto u = q.front();q.pop();for(auto v:edges[u]){if(a[v]==0){a[v] = 3-a[u];if(a[v]==1) cnt1+=1;else cnt2+=1;q.emplace(v);}else if(a[u]+a[v]!=3){ans = 0;break;}}}if(ans==0) break;//power(2,cnt)ans=ans*((power(t,cnt1)%P+power(t,cnt2)%P)%P)%P;}}
void solve(){std::cin >> n >> m;for(int i = 1;i<=n;++i){edges[i].clear();a[i] = 0;}ans = 1;while(m--){int u,v;std::cin >> u >> v;edges[u].emplace_back(v);edges[v].emplace_back(u);}bfs();std::cout << ans << '\n';
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.12 问题 L: 兔兔的导航系统

我的代码

原题:

2024算法基础公选课练习三(DFS1)的L题

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 2e5+5,M = 1e6+5,INF = 0x3f3f3f3f;int n,m,k;
std::vector<std::vector<int>> edges(N,std::vector<int>());
std::vector<std::vector<int>> reverse_edges(N,std::vector<int>());
std::vector<bool> vis(N,false);
std::vector<int> dist(N,INF);
std::vector<int> p(N,0);
int st,ed;
int maxn=0,minn=0;
void bfs() {std::queue<int> q;vis[st] = true;dist[st] = 0;q.emplace(st);while(!q.empty()) {auto t = q.front();q.pop();for(int i = 0;i<reverse_edges[t].size();++i) {int to = reverse_edges[t][i];if(vis[to]) continue;vis[to] = true;dist[to] = dist[t]+1;q.emplace(to);}}
}void solve(){std::cin >> n >> m;while(m--){int u,v;std::cin >> u >> v;edges[u].emplace_back(v);reverse_edges[v].emplace_back(u);}std::cin >> k;for(int i = 1;i<=k;++i) std::cin >> p[i];st = p[1],ed = p[k];bfs();for(int i = 1;i<=k-1;++i) {int u = p[i],v = p[i+1];bool flag = false;//用于判断是否当前u->v是最短路for(int j = 0;j<edges[u].size();++j) {int w = edges[u][j];if(dist[w]==dist[u]-1) {if(v==w) {flag = true;}else {++maxn;}}}if(!flag) ++minn,++maxn;}std::cout << minn << ' ' << maxn << '\n';
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;// std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

3.13 问题 M: 龙哥的换根树

我的代码

bfs两次,然后换根dp

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 2e5+5,M = 1e6+5,INF = 0x3f3f3f3f;
i64 n,k,c;
void bfs(int root,std::vector<std::vector<int>> &edges,std::vector<bool> &vis,std::vector<i64> &dist){std::queue<int> q;vis[root] = true;q.emplace(root);dist[root] = 0;while(!q.empty()){auto u = q.front();q.pop();for(auto &v:edges[u]){if(vis[v]) continue;vis[v] = true;dist[v] = dist[u]+1;q.emplace(v);}}
}
void solve(){std::cin >> n >> k >> c;std::vector<std::vector<int>> edges(n+5,std::vector<int>());std::vector<bool> vis(n+5,false);std::vector<i64> dist(n+5,INF);//vector建边for(int i = 1;i<=n-1;++i){int u,v;std::cin >> u >> v;edges[u].emplace_back(v);edges[v].emplace_back(u);}i64 ans=0,max=0,tmp=0,leaf=1;bfs(1,edges,vis,dist);//拷贝dist数组留用std::vector<i64> prev_dist(n+5);std::copy(dist.begin(),dist.end(),prev_dist.begin());//找到最远的叶子结点leaf和这个最远距离maxfor(int i = 1;i<=n;++i){if(dist[i]>max){max = dist[i];leaf = i;}}//初始化for(int i = 1;i<=n;++i){vis[i] = false;dist[i] = INF;}//以这个叶子结点为根进行bfsbfs(leaf,edges,vis,dist);//枚举换根到每个点最大价值for(int i = 1;i<=n;++i){ans = std::max(ans,dist[i]*k-prev_dist[i]*c);}std::cout << ans << '\n';
}
int main(){std::cin.tie(nullptr)->sync_with_stdio(false);int t = 1;std::cin >> t;for(int ti = 0;ti<t;++ti) {solve();}return 0;
}

http://www.ppmy.cn/server/145559.html

相关文章

Mybatis---MyBatis映射文件SQL深入、多表查询

目录 第一章&#xff1a;MyBatis映射文件SQL深入 1.动态SQL 语句之if标签 2. 动态SQL语句之where标签 3. 动态SQL语句之foreach标签 4. 提取公用的SQL语句 提取公用SQL片段 定义分页模板 第二章&#xff1a;多表查询 1. 多表设计 2.搭建开发的环境 3.多对一查询&…

关于按天切割Tomcat的catalina.out日志文件的配置

1、catalina.out 是 Tomcat 的标准输出和标准错误日志&#xff0c;通常输出到 Tomcat 安装目录下的 logs 文件夹中。这个日志文件会记录 Tomcat 启动、停止以及运行过程中产生的所有日志信息。 2、在Apache Tomcat中&#xff0c;日志文件catalina.out默认情况下不会自动按天切割…

.NET9 - Swagger平替Scalar详解(四)

书接上回&#xff0c;上一章介绍了Swagger代替品Scalar&#xff0c;在使用中遇到不少问题&#xff0c;今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。 下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。…

Kubernetes 还是 SpringCloud?

前些年&#xff0c;随着微服务的概念提出以及落地&#xff0c;不断有很多的公司都加入到了这场技术革新中&#xff0c;现在可谓是人人都在做和说微服务。 提到微服务&#xff0c;Java栈内&#xff0c;就不得不提SpringBoot、SpringCloud、Dubbo。 近几年&#xff0c;随着Cloud …

远离网上的广告和无用信息,自己动手搭建Tipask问答网站

文章目录 前言1.Tipask网站搭建1.1 Tipask网站下载和安装1.2 Tipask网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试4. 结语 前…

C++——多态(下)

目录 引言 多态 4.多态的原理 4.1 虚函数表指针 4.2 多态的原理 5.单继承和多继承关系的虚函数表 5.1 单继承中的虚函数表 5.2 多继承中的虚函数表 结束语 引言 接下来我们继续学习多态。 没有阅读多态&#xff08;上&#xff09;的可以点击下面的链接哦~ C——多态…

RabbitMQ的预取值详解

RabbitMQ的预取值&#xff08;Prefetch Value&#xff09;是一个关键概念&#xff0c;它决定了消费者在从队列中获取消息时&#xff0c;一次性可以获取的消息数量。这一机制对于优化消息分发和消费者的负载均衡至关重要。 什么是RabbitMQ的预取值&#xff1f; 预取值是指消费者…

前端项目的动态路由实现(vue)

一、引言 动态路由&#xff0c;很多场景是&#xff0c;有些页面必须是某些用户或者某些角色才能访问&#xff0c;所以呢&#xff0c;前端的代码即使不给页面的入口&#xff0c;但是要是直接在地址栏敲入相关地址页面还是可以被访问到。为了杜绝这种情况&#xff0c;就用到了动…