DP问题空间的优化

1. 消去作为“层数”的那一维

如果状态转移时需要用到这一层和上一层的信息,此时往往需要改变枚举顺序
例如:\(01\) 背包

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

int w[N], v[N];
int f[2][N], n, m;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ )   cin >> w[i] >> v[i];
    
    for(int i = 1; i <= n; i ++ )
    
        for(int j = 0; j <= m; j ++ )
        {
            f[i & 1][j] = max(f[i & 1][j], f[(i - 1) & 1][j]);
            if(j >= w[i])    f[i & 1][j] = max(f[i & 1][j], f[(i - 1) & 1][j - w[i]] + v[i]);
        }
    
    cout << f[n & 1][m] << endl;
    
}

2. 将作为“层数”的那一维修改为滚动数组

如果状态转移只会用到这一层和上一层的信息,说明任意时刻我们只会用到两层的信息,因此“层数”那一维只需要两层即可
例如:\(01\) 背包

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int n, m;
int f[1010];

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ ) {
        int v, w;   cin >> v >> w;
        for(int j = m; j >= v; j -- ) {  // !!!改变枚举顺序
            f[j] = max(f[j], f[j - v] + w);
        }
    }
    cout << f[m] << endl;
    return 0;
}

3. 总结

通过代码可以看出来:
[消去维度方法]空间节省的更多,毕竟它直接把一维消去了;但是对于可能需要修改代码逻辑(例如枚举顺序)。
[滚动数组方法]空间消耗是[消去维度方法]的两倍;但是它实现起来比较简单,只需要在所有用到层数那一维的地方加上 & 1 即可。

posted @ 2024-11-06 18:07  光風霽月  阅读(2)  评论(0编辑  收藏  举报