01 背包基础 - 空间优化 (滚动数组,一维阵列)

2017-09-03 11:39:16

writer:pprp

以很简单的一个动态规划问题为引入:

从左上角到右下角走过的路径和最大,问你最大为多少?

1、可以想到普通的dp

状态转移为: dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + arr[i][j];

2、采用滚动数组的方式-节约了不必要的空间

状态转移为:dp2[i%2][j] = max(dp2[(i+1)%2][j],dp2[i%2][j-1]) + arr[i][j];

3、采用一维阵列的方式更加节省空间

状态转移为:dp3[j] = max(dp3[j],dp3[j-1]) + arr[i][j];

图解:

代码如下:

/*
@theme:空间优化,滚动数组,只使用一维阵列
@writer:pprp
@begin:10:45
@end:11:36
@declare:从左上角到右下角的总和最多为多少?
@error:
@date:2017/9/3
*/

#include <bits/stdc++.h>

using namespace std;
const int maxn = 100;
int arr[maxn][maxn];
int dp[maxn][maxn];
int dp2[2][maxn];
int dp3[maxn];
int n, m;

void init()
{
    freopen("in.txt","r",stdin);
    memset(dp,0,sizeof(dp));
    memset(arr,0,sizeof(arr));
    memset(dp2,0,sizeof(dp2));
    memset(dp3,0,sizeof(dp3));
    cin >> n >> m;
    for(int i = 0 ; i < n; i++)
    {
        for(int j = 0 ; j < m ; j++)
        {
            cin >> arr[i][j];
        }
    }
}

//普通简单dp
int fun1()
{
    dp[0][0] = arr[0][0];
    for(int i = 1; i < n ; i++)
    {
        dp[i][0] += arr[i][0] + dp[i-1][0];
    }
    for(int j = 1; j < m ; j++)
    {
        dp[0][j] += arr[0][j] + dp[0][j-1];
    }
    for(int i = 0 ; i < n ; i++)
    {
        for(int j = 0 ; j < m ; j++)
        {
            dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + arr[i][j];
        }
    }

    return dp[n-1][m-1];
}

//滚动数组
int fun2()
{
    dp2[0][0] = arr[0][0];
    for(int i = 1 ; i < m ; i++)
        dp2[0][i] += dp2[0][i-1] + arr[0][i];
    for(int i = 0  ; i < n ; i++)
    {
        for(int j = 0 ; j < m ; j++)
        {
            dp2[i%2][j] = max(dp2[(i+1)%2][j],dp2[i%2][j-1]) + arr[i][j];
        }
    }
    return dp2[(n-1)%2][m-1];
}

//一维阵列
int fun3()
{
    for(int i = 0 ; i < n ; i++)
    {
        dp3[0] = arr[i][0];
        for(int j = 1 ; j < m ; j++)
        {
            dp3[j] = max(dp3[j],dp3[j-1]) + arr[i][j];
        }
    }
    return dp3[m-1];
}

int main()
{
    init();
    cout << fun1() << endl;
    cout << "-----" << endl;
    for(int i = 0 ; i < n ; i++)
    {
        for(int j = 0 ; j < m ; j++)
            cout << dp[i][j] << " ";
        cout << endl;
    }
    cout << endl;
    cout << fun2() << endl;
    cout << "-----" << endl;
    for(int i = 0 ; i < m ; i++)
    {
        cout << dp2[0][i] << " ";
    }
    cout << endl;
    for(int i = 0 ; i < m ; i++)
    {
        cout << dp2[1][i] << " ";
    }
    cout << endl;
    cout << "-----" << endl;
    cout << fun3() << endl;

    return 0;
}
时间: 2024-09-30 09:34:01

01 背包基础 - 空间优化 (滚动数组,一维阵列)的相关文章

01背包基础 (杭电2602)

01背包问题: 有一个体积为V的背包,有n件物品,每件物品的体积,价值分别为w[i],p[i];要从n件物品中选些放入背包中,使背包里物品的总价值最大. 动态方程:c[i][j]=max(c[i-1][j],c[i-1][j-w[i]]+p[i]). 有关动态方程方面的代码: for (int i = 1; i <= n; i++) { for (int j = 1; j <= total_weight; j++) { if (w[i] > j) { c[i][j] = c[i-1][j

NYOJ 654喜欢玩warcraft的ltl(01背包/常数级优化)

传送门 Description ltl 非常喜欢玩warcraft,因为warcraft十分讲究团队整体实力,而他自己现在也为升级而不拖累团队而努力. 他现在有很多个地点来选择去刷怪升级,但是在每一个地点他都要买上充足的补给和合适的道具,以免在刷怪的时候被怪物反杀了,每一个地点的怪物打完了就没有了(还居然不掉金钱跟装备),而且他只要选定了地点就一定会刷完该地点全部的怪物,同时获得对应的经验值.现在ltl 能给出每一个地点用来买补给和道具的钱和打完全部怪物所能获得的经验,但是他所拥有的钱是一定的.

Jam&#39;s balance HDU - 5616 (01背包基础题)

Jim has a balance and N weights. (1≤N≤20) The balance can only tell whether things on different side are the same weight. Weights can be put on left side or right side arbitrarily. Please tell whether the balance can measure an object of weight M. In

01背包问题(空间优化)经典代码

题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 基本思路 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值.则其状态转移方程便是: f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的.所以有必要将它详细解释一下

一些常见的优化:读入优化,滚动数组

1.读入优化 我们平时所使用的scanf,cin速度都较慢,当读入的数据达到10^5规模以上时,就会开始显现劣势 而c中自带的getchar函数读入速度较快,可以用来优化数字的读入速度. 1 inline int get_num() 2 { 3 int num = 0; 4 char c; 5 bool flag = false; 6 while ((c = getchar()) == ' ' || c == '\n' || c == '\r'); 7 if (c == '-') flag =

一道简单的递推题(快速幂+矩阵乘法优化+滚动数组)

问题 F: 一道简单的递推题 时间限制: 1 Sec  内存限制: 128 MB提交: 546  解决: 48[提交][状态][讨论版] 题目描述 存在如下递推式: F(n+1)=A1*F(n)+A2*F(n-1)+...+An*F(1) 求第K项的值对1000000007取模的结果 输入 单组测试数据 第一行输入两个整数 n , k (1<=n<=100,n<k<=10000000000) 第二行输入 n 个整数 F(1)   F(2)   ...   F(n) 第三行输入 n

POJ - 3624 Charm Bracelet (01背包基础)

题意: 即是给你一个容量M的包,有N件物品,每件物品有分别对应的 价值value 以及 重量weight .然后在不超过该背包容量的情况下能得到的最大价值为多少? 思路: 由于这是最基础的问题,所以就记录当对 01背包状态转移方程式的 理解. 对于动态规划来说,首先要知道我们要确定哪些状态量.然后再基于这些状态量进行状态转移得到我们最后希望得到的答案. 比如对于序列求最值来说我们习惯记录最后位取的是谁(即末位j),那么同理我们也可以记录我们当前选的是哪一种 物品.同时容量在状态中是必不可少的,所

01背包思想和优化

dp入门问题:01背包装下了我们的忧伤QWQ 作为一枚乐于作死...呸,乐于学习的蒟蒻,当然要学会装包的 那么简单的描述一下01背包问题: 小明有个bag,容量是m.小明面前有n个物品,每个物品有它的价值vi和它的体积wi,小明想知道用这个背包能装到的物品总价值最大是多少. 好,这就是一个最朴素的01背包问题,那么怎么解决呢. 稍加思索...dp嘛,从小问题解决到大问题.我们用一个数组dp[i][j]表示选第i件物品时容量为j可以得到的最大价值. 状态转移方程就出来啦:dp[i][j]=max(

01背包 基础

The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while,