草庐IT

关于滚动数组的一些菜鸟随笔

whf10000010 2023-03-28 原文

什么是滚动数组

    简单来说,滚动数组就是一种具有短暂记忆力的数组,它会牺牲时间来节省空间,用size=3的数组来“存储”30000个数据。这么说有点离谱、抽象,毕竟a[3]怎么存储a[30000]里面的东西呢。这就是滚动数组的特性,即只记录少量的后续需要使用的数据,而将之前用过且不再需要调用的数据抛弃、覆盖,这样就将a[30000]中不要的数据所占的空间节省出来,以达到a[3]就能达成的任务目标。

滚动数组的核心:取余

    在开始学习C语音的时候,接触到了一个新的数学运算符:取余%,和除号 / 类似的是都多用在特殊的循环或者是取一串数字的某一位,除法多取高位,取余多取低位。在滚动数组中,取余用于数组下标的动态改变,以达到[3]存[30000]的效果,例如:

int m=30000;//一个原先大的数据空间
int n=3;//所需要的一个滚动数组空间
void fun()
{

    for (int i = 0; i < m; i++)
    {
        d[i % n] = d[(i - 1) % n] + d[(i - 2) % n];
    }
}

    通过取余的特点可以看出,动态数组在取模和循环的作用下只用3个空间就可以做到存储30000个数据的作用。

使用情况(浅提动态规划)

  那什么时候使用呢?

  1. 在不在意时间,只需要节省空间的情况。滚动数组的本质是通过for循环多次覆盖不用的数值,增加了时间,又使用取余动态改变数组下标,节省了空间。
  2. 多用于动态规划问题(Dynamic Programing,DP)。  

  在这不得不说到动态规划问题,但由于篇幅所限,在此仅浅谈一下,后续有缘更新。DP主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。

    多阶段决策过程的特点是每个阶段都要进行决策,具有n个阶段的决策过程的策略是由n个相继进行的阶段决策构成的决策序列。由于前阶段的终止状态又是后一阶段的初始状态,因此确定阶段最优决策不能只从本阶段的效应出发,必须通盘考虑,整体规划。就是说,阶段k的最优决策不应只是本阶段的最优,而必须是本阶段及其所有后续阶段的总体最优。

   而DP 的有最重要的两个理论--最优化原理和无后效性原则

例题说明

  斐波那契数列

  1. 因为乘数指定,即只有一条路能走,故符合最优原理。
  2. 乘积固定,没有其它因素影响,所以符合无后效性原则。

因此可以使用滚动数组方法,代码:

 1 void func2()
 2 {
 3     int d[3];
 4     d[0] = 1;
 5     d[1] = 1;
 6     for (int i = 0; i < 100; i++)
 7     {
 8         d[i % 3] = d[(i - 1) % 3] + d[(i - 2) % 3];
 9     }
10     printf("%d", d[99 % 3]);
11 }

  01背包

  1. 整体最优是由一步步的子问题最优组成,即n个空间的包最优解是由1~n-1个空间背包的最优解组合而成,故符合最优原理。
  2. 每个数值固定,无论前面问题是怎样解,后面背包总空间不变,往后的任何决策都不会改变。故符合无后效性。

因此可以使用滚动数组方法,代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e3+10;
 4 int t,n,v;
 5 int dp[maxn];
 6 int value[maxn];
 7 int weight[maxn];
 8 int main()
 9 {
10     scanf("%d",&t);
11     while(t--)
12     {
13         memset(dp,0,sizeof dp);
14         scanf("%d %d",&n,&v);
15         for(int i = 1;i <= n;i++)
16             scanf("%d",&value[i]);
17         for(int i = 1;i <= n;i++)
18             scanf("%d",&weight[i]);
19         // for(int i = 1;i <= n;i++)    原始二维dp方程
20         //     for(int j = 0;j <= v;j++)
21         //     {
22         //         if(j >= weight[i])        //若取得下,则可以选择取或不取
23         //             dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
24         //         else    
25         //             dp[i][j]=dp[i-1][j];
26         //     }
27         for(int i = 1;i <= n;i++)    //使用滚动数组优化后的dp方程
28             for(int j = v;j >= weight[i];j--)    //倒序保证数据更新的有序性,保证只取一次,正序则是完全背包的写法
29                 dp[j]=max(dp[j],dp[j - weight[i]] + value[i]);
30         printf("%d\n",dp[v]);
31     }
32     return 0;
33 }

<-------------------------------------------------------------------------------------------->

最后,滚动数组只是动态问题中的一小部分,后续还有更多有趣的知识,例如动态问题和搜索、分治法的联系和区别,随缘更新。By the way,更新这篇时正赶上国庆,摆了几天,当我正常学习的时候,电脑开摆了,这么点字,它疯狂蓝屏、黑屏,问题是没保存,导致写了好几次,有些小细节因为写太多烦了,就没打,现在反而忘了,华硕天选2,你恶事做尽!!!!

文章部分节选:

动态规划之滚动数组 - shawchakong - 博客园 (cnblogs.com)

滚动数组(简单说明)_儒rs的博客-CSDN博客_滚动数组

有关关于滚动数组的一些菜鸟随笔的更多相关文章

  1. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  2. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  3. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  4. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  5. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  6. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  7. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  8. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  9. ruby - 使用多个数组创建计数 - 2

    我正在尝试按0-9和a-z的顺序创建数字和字母列表。我有一组值value_array=['0','1','2','3','4','5','6','7','8','9','a','b','光盘','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','','u','v','w','x','y','z']和一个组合列表的数组,按顺序,这些数字可以产生x个字符,比方说三个list_array=[]和一个当前字母和数字组合的数组(在将它插入列表数组之前我会把它变成一个字符串,]current_combo['0','0','0']

  10. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

随机推荐