C++算法之双指针、BFS和图论

2024-02-09 18:12
文章标签 算法 c++ 指针 图论 bfs 之双

本文主要是介绍C++算法之双指针、BFS和图论,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、双指针

1.AcWing 1238.日志统计

分析思路

前一区间和后一区间有大部分是存在重复的
我们要做的就是利用这部分 来缩短我们查询的时间
并且在使用双指针时要注意对所有的博客记录按时间从小到大先排好顺序
因为在有序的区间内才能使用双指针记录两个区间相差
相当于把一个有序的时间序列进行每次递增1的划分

代码实现
#include<iostream>
#include<algorithm>#define x first
#define y second
using namespace std;
const int N=100010;
typedef pair<int,int>PII;
PII logs[N];
bool st[N];
int cnt[N];
int main()
{int n,d,k;cin>>n>>d>>k;for(int i=0;i<n;i++) cin>>logs[i].x>>logs[i].y;sort(logs,logs+n);for(int i=0,j=0;i<n;i++){int t=logs[i].y;cnt[t]++;while(logs[i].x-logs[j].x>=d){cnt[logs[j].y]--;j++;}if(cnt[t]>=k) st[t]=true;}for(int i=0;i<100000;i++){if(st[i]) cout<<i<<endl;}return 0;
}

2.AcWing 1240.完全二叉树的权值  

分析思路

双指针:

从第一层根节点i=1,开始每一层开头都是2i,而每一层的长度就为pow(2,d-1)(d为层数)

前缀和:

因为是完全二叉树,所以算到最后要考虑是否越界。

代码实现

双指针

#include<bits/stdc++.h>using namespace std;
typedef long long LL;
const int N=100010;
int q[N];
LL sum[N];
int n,t;int main()
{scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&q[i]);LL m=-1e18;for(int i=1,d=1;i<=n;i*=2,d++){LL s=0;for(int j=i;j<i+pow(2,d-1)&&j<=n;j++) s+=q[j];if(s>m){m=s;t=d;}}cout<<t<<endl;return 0;
}

前缀和

#include<bits/stdc++.h>using namespace std;
typedef long long LL;
const int N=100010;
int q[N];
LL sum[N];
int n,t;int main()
{scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&q[i]);for(int i=1;i<=n;i++) sum[i]=sum[i-1]+q[i];LL m=-1e18;for(int i=1,d=1;i<=n;i*=2,d++){LL s=0;LL r=i+pow(2,d-1)-1;if(r<=n) s=sum[r]-sum[i-1];else s=sum[n]-sum[i-1];if(s>m){m=s;t=d;}}cout<<t<<endl;return 0;
}

二、BFS

1.AcWing 1101.献给阿尔吉侬的花束

分析思路

BFS广度优先遍历,就是队首出队,然后与队首相关的入队。上图为模拟过程!

代码实现
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>#define x first
#define y secondusing namespace std;typedef pair<int,int> PII;const int N=210;int n,m;
char g[N][N];
int dist[N][N];int bfs(PII start,PII end)
{//队列queue<PII>q;memset(dist,-1,sizeof dist);//初始化距离为-1;dist[start.x][start.y]=0;q.push(start);int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};while(q.size())//队列不为空{auto t=q.front();//队首q.pop();//枚举四种方向上的情况for (int i = 0; i < 4; i ++ ){int x = t.x + dx[i], y = t.y + dy[i];if (x < 0 || x >= n || y < 0 || y >= m) continue;  // 出界if (g[x][y] == '#') continue;  // 障碍物if (dist[x][y] != -1) continue;  // 之前已经遍历过dist[x][y] = dist[t.x][t.y] + 1;if (end == make_pair(x, y)) return dist[x][y];q.push({x, y});}}return -1;
}int main()
{int t;cin>>t;while(t--){cin>>n>>m;for(int i=0;i<n;i++) scanf("%s",g[i]);//读入的是字符串,不需要加&PII start,end;//起点与终点for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(g[i][j]=='S') start={i,j};else if(g[i][j]=='E') end={i,j};}}int distance = bfs(start, end);if (distance == -1) puts("oop!");else printf("%d\n", distance);}return 0;
}

2.AcWing 1096.地牢大师

分析思路

二维上多加了一维,就有六个方向,读入用二维读入。

代码实现
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>using namespace std;struct Point
{int x,y,z;  
};const int N=100;
char g[N][N][N];
int dist[N][N][N];
int l,r,c;
Point q[N * N * N];
int dx[6] = {1, -1, 0, 0, 0, 0};
int dy[6] = {0, 0, 1, -1, 0, 0};
int dz[6] = {0, 0, 0, 0, 1, -1};int bfs(Point start,Point end)
{int hh=0,tt=0;q[0]=start;memset(dist,-1,sizeof dist);dist[start.x][start.y][start.z]=0;while(hh<=tt){auto t=q[hh++];for(int i=0;i<6;i++){int x=t.x+dx[i],y=t.y+dy[i],z=t.z+dz[i];if(x<0||y<0||z<0||x>=l||y>=r||z>=c) continue;if(g[x][y][z]=='#'||dist[x][y][z]!=-1) continue;dist[x][y][z]=dist[t.x][t.y][t.z]+1;if(g[x][y][z]=='E') return dist[x][y][z];q[++tt]={x,y,z};}}return -1;}int main()
{while(cin>>l>>r>>c,l||r||c){Point start,end;for(int i=0;i<l;i++){for(int j=0;j<r;j++){scanf("%s",g[i][j]);//三维用两维来存for(int k=0;k<c;k++){if(g[i][j][k]=='S') start={i,j,k};else if(g[i][j][k]=='E') end={i,j,k};}}}int distance=bfs(start,end);if(distance==-1) puts("Trapped!");else printf("Escaped in %d minute(s).\n",distance);}return 0;
}

用队列的方式: 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>using namespace std;struct Point
{int x,y,z;  
};const int N=100;
char g[N][N][N];
int dist[N][N][N];
int l,r,c;int dx[6] = {1, -1, 0, 0, 0, 0};
int dy[6] = {0, 0, 1, -1, 0, 0};
int dz[6] = {0, 0, 0, 0, 1, -1};int bfs(Point start,Point end)
{queue<Point> q;int hh=0;q.push(start);memset(dist,-1,sizeof dist);dist[start.x][start.y][start.z]=0;while(q.size()){auto t=q.front();for(int i=0;i<6;i++){int x=t.x+dx[i],y=t.y+dy[i],z=t.z+dz[i];if(x<0||y<0||z<0||x>=l||y>=r||z>=c) continue;if(g[x][y][z]=='#'||dist[x][y][z]!=-1) continue;dist[x][y][z]=dist[t.x][t.y][t.z]+1;if(g[x][y][z]=='E') return dist[x][y][z];q.push({x,y,z});}q.pop();}return -1;}int main()
{while(cin>>l>>r>>c,l||r||c){Point start,end;for(int i=0;i<l;i++){for(int j=0;j<r;j++){scanf("%s",g[i][j]);//三维用两维来存for(int k=0;k<c;k++){if(g[i][j][k]=='S') start={i,j,k};else if(g[i][j][k]=='E') end={i,j,k};}}}int distance=bfs(start,end);if(distance==-1) puts("Trapped!");else printf("Escaped in %d minute(s).\n",distance);}return 0;
}

这篇关于C++算法之双指针、BFS和图论的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/694944

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个