动态规划有一个很重要的特点:无后效性,意思是当前状态的决策不受过去决策的影响。所以当状态很多时,我们不必去保存所有的状态,这样很占用内存,我们只需保存与当前决策有关的状态即可。
下面以斐波那契数列为例。求f[100]时,我们通常时利用是开一个100的数组空间。可是f[100]=f[99]+f[98],其只与它的前两个状态有关,此外,像f[i]=f[i-1]+f[i-2],每一个数都只和它的前两个状态有关,所以我们实际上只需要开一个3的空间,就可以通过不断的迭代,只保留与当前决策有用的状态而之前的无用信息全部舍去。这就是滚动数组。下面上两个斐波那契代码
普通做法
#include<iostream> #include<cstdio> using namespace std; int f[100]; int ff(int n) { f[0] = 0; f[1] = 1; f[2] = 1; for(int i = 3; i <= n; ++i) f[i] = f[i - 1] + f[i - 2]; return f[n]; } int main() { int t, n; scanf("%d", &t); while(t--) { scanf("%d", &n); printf("%d\n", ff(n)); } return 0; }
滚动数组
#include<cstdio> using namespace std; int f[3]; int ff(int n) { f[1] = 0; f[2] = 1; for(int i = 2; i <= n; ++i) { f[0] = f[1]; f[1] = f[2]; f[2] = f[0] + f[1]; } return f[2]; } int main() { int t, n; scanf("%d", &t); while(t--) { scanf("%d", &n); printf("%d\n", ff(n)); } return 0; }