ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

滚动数组的几种写法

2021-09-14 16:31:21  阅读:215  来源: 互联网

标签:状态 滚动 转移 vector 数组 下标 写法 memcpy


当然,原地滚动永远是最优的(比如:经典的背包问题)

滚动数组适用的条件

打个比方,某dp的转移方程如下
f[i][x] = min(f[i-1][a],f[i-2][b],...,f[i-j][k]
i的状态仅仅取决于(i-1,...,i-j)这j个状态,而与更之前的状态无关
那么更之前的状态我们可以不用保存, 只需要保存待转移的状态转移需要的状态
(这里状态指的是某维度,如 i,i-1)
所以,我们必须能够确定转移需要的状态的最大数目,才能使用滚动数组优化

滚动数组的几种写法

特殊情况,只取决于上一个维度的状态

  1. 利用相邻两个数奇偶性不同这一性质 进行转移
    例子:acwing292炮兵阵地的转移方程
    f[i & 1][j][k] = max(f[i & 1][j][k], f[i - 1 & 1][u][j] + cnt[c]);
  2. 把数组当作变量,交换即可
memcpy(tmp,f[2],sizeof f[2]);
memcpy(f[2],f[1],sizeof f[1]);
memcpy(f[1],tmp,sizeof f[1]);

注:memcpy是对数组元素逐个拷贝的,所以会很慢,此外std::swap()对数组进行交换也是逐个拷贝的,运行效率比memcpy还要慢

当前状态取决于前x个的状态

随着dp的遍历,最后一个状态会变成无用的状态,该状态的空间被拿来重复利用,问题在于如何确定下标,如何减少复杂度
1.取模运算

假设 算上待转移的状态共有x个状态,那么我们用 i mod x得到对应下标(0...x-1)因为这x个状态是连续的,所以必然可以不重不漏的找到对应下标

2.把数组当成元素,进行交换

末尾的状态 i - x将来用不到,于是把所有状态的值向前平移,腾出位子
不过这样实在是太低效了,又要拷贝元素什么的
但是!! 使用vector就可以避免拷贝.swap对容器和适配器类型是进行交换指针,速度非常快
不过对多维数组的定义比较麻烦
比如自己的某题的定义
vector<vector<vector<int>>>f(2,vector<vector<int>>(1<<M,vector<int>(1<<M,0)));

所以,如果对下标拿捏不定,不如就用vector来搞定。
嫌vector定义太麻烦,就用取模运算咯

点个赞再走? 靓仔

标签:状态,滚动,转移,vector,数组,下标,写法,memcpy
来源: https://blog.csdn.net/qq_46096608/article/details/120290489

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有