滚动数组浅析

滚动数组浅析

很久之前就听说过 “滚动数组”这个东东,只是做题太少,出于一定原因一直没有拿出时间来研究研究,今天系统的整理动态规划的内容时,再次邂逅,于是乎,决定对其研究一二。

那么什么是滚动数组呢?相信很多同学在做动态规划之类的一些题目时,往往会遇到MLE的问题吧?!滚动数组就是应景而生,其实就是循环利用一些空间,从而达到优化空间的目的。最简单的解释就是在DP状态转移方程中,对我们而言有需要的仅仅是之前两个或者几个状态,在递推求解时,我们便可以利用这样一个便利解题。但是,需要注意的就是,如何滚动?重点也就是如何进行"滚动"以及如何用表达式控制这个滚动。

举个例子:

在一维的情形下:

int i,d[100];

d[0] = 1;

d[1] = 1;

for (i = 2; i< 100; i++)

   d[i] = d[i - 1] + d[i - 2];

printf("%d",d[99]);

在当前这个状态(循环)下,d[i]只依赖于前两个数据d[i - 1]和d[i - 2];

那么,为了节约空间我们用滚动数组的做法为:

int d[3];

d[0] = 1;

d[1] = 1;

for (i = 2; i< 100; i++)

   d[i % 3] = d[(i - 1) % 3] + d[(i - 2) % 3];

printf("%d",d[99 % 3]);

注意上面的取余运算,我们成功地只保留了需要的最后3个解,数组好象在“滚动”一样,所以叫滚动数组,或者说我们在循环的利用某几段空间,所以又可以称作循环滚动数组。

 

同样的,在二维的情形下,同样适用于某些状态:

int i,j,d[100][100];

for(i=1;i<100;i++)

    for(j=0;j<100;j++)

       d[i][j]=d[i-1][j]+d[i][j-1];

 

上面的d[i][j]只依赖于d[i-1][j],d[i][j-1];

运用滚动数组

int i,,j,d[2][100];

for(i=1;i<100;i++)

    for(j=0;j<100;j++)

       d[i%2][j]=d[(i-1)%2][j]+d[i%2][j-1];

       滚动数组虽好,但也存在一些不尽人意的地方,比如打印方案比较困难,当DP结束后,只有最后一个阶段的状态值,而丢失了前面的值,事实上,对于01背包问题下的,“前i个物品”这样的规划方向,只能使用逆向的打印方案,而且还不能保证它的字典序最小。

所以在需要打印方案甚至要求字典序最小方案的场合,应慎用!


具体实例见POJ 1159,带详细解析。



  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值