当前位置: 首页 > news >正文

算法 模版

cin cout加快读取速度:

ios::sync_with_stdio(false);

高精度*高精度

vector<int> mul(vector<int>& a, vector<int>& b) {
	vector<int>c(b.size()+a.size()+5,0);
	for (int i = 0; i < a.size(); i++) {
		for (int j = 0; j < b.size(); j++) {
			c[i + j] += a[i] * b[j];
		}
	}
	for (int i = 0; i < c.size(); i++) {
		if (c[i] > 9) {
			c[i + 1] += c[i] / 10;
			c[i] = c[i] % 10;
		}
	}
	while (c.size() > 1 && c.back() == 0)c.pop_back();
	return c;
}

高精度+高精度

vector<int> add(vector<int> &A, vector<int> &B)
{
    if (A.size() < B.size()) return add(B, A);

    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }

    if (t) C.push_back(t);
    return C;
}

二分:

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 求右边界时用,满足右区间性质为true
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 求左边界时用,满足左区间性质为true
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

int res=upper_bound(num,num+n,q)-num;

int res=lower_bound(num,num+n,q)-num;

upper寻找第一个大于q的数的地址,lower寻找第一个大于等于q的数的地址。在"algorithm"库中。

 滑动窗口:

//进窗口
......
//处理结果
......
//出窗口
......

动态规划:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组
  • 01背包:物品只有一个。dp[i][j]从前i个物品中选,容量为j时选择的最大价值是dp[i][j]。

 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);区别就是对i物品选与不选。

  • 完全背包:每个物品无数个。dp[i][j]定义一样。

dp[i][j]=max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);

两者在选择i物品上有区别,

dfs:

深搜三步曲:

1.确定递归函数,参数

2。确认终止条件

3.处理目前搜索节点出发的路径

void dfs(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本节点所连接的其他节点) {
        处理节点;
        dfs(图,选择的节点); // 递归
        回溯,撤销处理结果
    }
}

bfs:

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {
    queue<pair<int, int>> que; // 定义队列
    que.push({x, y}); // 起始节点加入队列
    visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点
    while(!que.empty()) { // 开始遍历队列里的元素
        pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素
        int curx = cur.first;
        int cury = cur.second; // 当前节点坐标
        for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过
            if (!visited[nextx][nexty]) { // 如果节点没被访问过
                que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点
                visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问
            }
        }
    }

}

快排:

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;
 
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
 

归并排序:

void merge_sort(int q[], int l, int r) {
	if (l >= r)return;
	int mid = l + r >> 1;
	merge_sort(q, l, mid);
	merge_sort(q, mid + 1, r);
	int k = 0, i = l, j = mid+1;
	while (i <= mid && j <= r) {
		if (q[i] <= q[j])tmp[k++] = q[i++];
		else tmp[k++] = q[j++];
	}
	while (i <= mid) { tmp[k++] = q[i++]; }
	while (j <= r) { tmp[k++] = q[j++]; }
	for (int i = l,j=0;i<=r;i++,j++) q[i] = tmp[j];
}

前缀与差分:

a[n]是b[n]的前缀和数组,b[n]是a[n]的差分数组。

a[n]=b[1]+b[2]+...+b[n]。b[n]=a[n]-a[n-1]。

如果对a数组l到r均+c,那么只需对b数组b[l]+c,b[r+1]-c。

如果求b数组从l到r的和,那么只需查询a[r]-a[l]。

并查集:

1.将两个元素添加到同一个集合中。

2.判断两个元素在不在同一个集合中。

int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
vector<int> father = vector<int> (n, 0); // C++里的一种数组结构

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}
// 并查集里寻根的过程
int find(int u) {
    if (u == father[u]) return u;
    else return father[u] = find(father[u]); // 路径压缩
}
// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找v的根
    if (u == v) return ; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
    father[v] = u;
}

最小生成树:

prim三部曲:

1.选距离生成树最近节点

2.最近节点加入生成树

3.更新非生成树节点到生成树的距离(即更新minDist数组)

Kruskal算法:

思路:边的权值排序,因为要优先选最小的边加入到生成树里。

遍历排序后的边,如果边收尾的两个节点在同一个集合中,说明如果连上这条边图中会出现环;如果边首尾的两个节点不在同一个集合,加入到最小生成树,并把两个节点加入同一个集合

相关文章:

  • 408 计算机网络 知识点记忆(8)
  • 数据可视化 —— 堆形图应用(大全)
  • 在windows服务器使用Nginx反向代理云端的python实现的web应用
  • 极简cnn-based手写数字识别程序
  • 生成验证码图片
  • shell编程之条件语句
  • 从原始新闻数据中筛选出 正文内容超过 1024 个词(token) 的新闻,并将其保存到新文件中。
  • Linux __命令和权限
  • 两个树莓派如何通过wifi direct传输视频并显示
  • 二分查找4:35. 搜索插入位置
  • AI 笔记 - 开源轻量级人脸检测项目
  • 内联函数通常定义在头文件中的原因详解
  • STL之无序关联式容器针对于自定义类型的操作
  • 使用克魔助手查看iOS 应用程序使用历史记录和耗能历史记录
  • 数字政府网络架构建设方案
  • 创新驱动:智慧养老综合实训室内的前沿技术应用
  • Asp.NET Core WebApi IOptions<T>详解
  • Linux关于git上传大文件的解决方案:使用Git LFS
  • 【遥感科普】多光谱和高光谱卫星影像有什么区别?
  • 介绍一下freertos
  • 90设计网是干嘛的/青岛网络优化哪家专业
  • 罗湖企业网站建设/许昌网站推广公司
  • 绵阳市建设局官方网站/百度网盘资源链接入口
  • 一般网站如何做防采集的/广州网站运营专注乐云seo
  • 在哪个网站去租地方做收废站/中国企业500强排行榜
  • 广东省政府网站集约化平台建设/抖音推广