所谓滚动数组,目的在于优化空间,从上面的解法我们可以看到,状态转移矩阵使用的是一个N*V的数组,在求解的过程中,我们可以发现,当前状态只与前一状态的解有关,那么之前存储的状态信息已经无用了,可以舍弃的,我们只需要空间存储当前的状态和前一状态,所以只需使用2*V的空间,循环滚动使用,就可以达到跟N*V一样的效果。这是一个非常大的空间优化。
代码如下,我们可以在每轮内循环结束后输出当前状态的解,与上面使用二维数组输出的状态转移矩阵对比,会发现是一样的效果,重定向输出到文本有助加深理解。
#include using namespace std; int maxValue[2][201]; int weight[11]; int value[11]; int V, N; void main() { int i,j, k; scanf("%d %d",&V, &N); for(i= 0; i < N; ++i) { scanf("%d%d",&weight[i],&value[i]); } for(i= 0; i < N; ++i) { for(j = 0; j <= V;++j) { if(i > 0) { k = i& 1; maxValue[k][j] = maxValue[k^1][j]; if(j >=weight[i]) { int tmp =maxValue[k^1][j-weight[i]] + value[i]; maxValue[k][j] = ( tmp >maxValue[k][j]) ? tmp : maxValue[k][j]; } }else { if(j >=weight[0]) maxValue[0][j] =value[0]; } } } printf("%d",maxValue[k][V]); freopen("C:\\dp.txt","w",stdout); for(i= 0; i <= 1; ++i) { for(j = 0; j <= V;++j) { printf("%d ",maxValue[i][j]); } printf("\n"); } }
这种空间循环滚动使用的思想很有意思,类似的,大家熟悉的斐波那契数列,f(n) =f(n-1) +f(n-2),如果要求解f(1000),是不需要申请1000个大小的数组的,使用滚动数组只需申请3个空间f[3]就可以完成任务。
========================================