滚动数组

滚动数组。它常被用来完成常数优化和减少代码量。

假设有如下状态转移方程:

dp[i][j]= max(dp[i1][j +1],dp[i1][j 1]);

按照该状态转移方程,我们可以用二维数组保存其状态值,通过如下代码片段完成其状态的转移(这里仅作说明,不考虑边界情况): 

for (int i = 1;i <= n;i ++) {
    for (int j = 1;j <= m;j ++) {
       dp[i][j] = max(dp[i - 1][j + 1],dp[i - 1][j - 1]);
    }
}
int ans = dp[n][m];

考虑到每次状态的转移仅与上一行有关,我们可以将二维数组优化到使用一维数组保存。如下: 

for (int i = 1;i <= n;i ++) {
    for (int j = 1;j <= m;j ++) {
       buf[j] = max(dp[j + 1],dp[j - 1]);
    }
    for (int j = 1;j <= m;j ++) {
      dp[j] = buf[j];
    }
}
int ans = dp[m];

如该代码片段所示,我们将原本二维的状态空间优化到了一维,对应的我们需要在每次状态转移过后进行一次循环次数为m 的赋值操作。该操作不仅增加了代码量,还增加了程序的耗时。于是我们使用滚动数组,对其再次进行优化:

定义大小为2*m 的数组为其状态空间: 

int dp[2][M]

初始状态保存在dp[0][i]中。

设定两个int 类型指针 

  int *src; //源指针 
  int *des;//目的指针

由于初始状态保存在 dp 数组的第 0 行中,初始时 

src=dp[1];
des=dp[0];

按照状态转移方程进行状态转移 

for (int i = 1;i <= n;i ++) { 
  swap(src,des); //交换源和目的指针 
  for (int j = 1;j <= m;j ++) {
       des[j] = max(src[j + 1],src[j - 1];
    }
}
int ans = des[m];

如代码所示,我们在每次循环进行状态转移之前交换源数组和目的数组的指针,使程序能够正确的从源数组中转移状态到目的数组中。当状态转移完成时,新得到状态保存于目的数组中,但它在下一次循环的状态转移中又将变为源数组,于是我们在下次状态转移开始前再次交换源数组和目的数组指针,这就是滚动数组的工作原理。

滚动数组这个技巧不仅优化了原始的状态空间,还减少了循环次数节约了程序运行时间,同时对代码量的缩减也有很好的效果,是一个我们值得学习的小技巧。 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值