其他分享
首页 > 其他分享> > 动态规划学习笔记(updating)

动态规划学习笔记(updating)

作者:互联网

背包问题:

  01背包问题:

    朴素版:(二维数组)

      状态表示: dp[i][j]:从前i个物品中选择且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案(n:物品数量,m:最大体积)

      状态计算: dp[i][j] = max ( dp[i-1][j] , dp[i-1][j-vi]+wi )  // 由含i和不含i两个子集合计算而来(vi:物品体积,wi:物品价值)

      核心代码:

int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N][M];

void keyCode()
{
    for(int i = 1; i <= n; i++) 
        for(int j = 0; j <= m; j++) 
        {
            dp[i][j] = dp[i-1][j];
            if(v[i] >= j) dp[i][j] = max(dp[i][j], dp[i-1][j-v[i]] + w[i]); 
        }
}

    空间优化版:(滚动数组,二维数组优化至一维)

  状态表示:dp[j]:在外循环的第i层时,表示从前i个物品中选择且总体积不超过j的集合的最大价值,n层循环后,dp[m]就是最终答案

  状态计算:dp[j] = max ( dp[j] , dp[j-vi]+wi )  // 由含i和不含i两个子集合计算而来

  核心代码:

int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N];

void keyCode()
{
    for(int i = 1; i <= n; i++) 
        // 反向遍历, 否则dp[j-v[i]]可能为dp[i][j-v[i]](用更新后的值来更新导致出错)
        for(int j = m; j >= v[i]; j--) 
            dp[j] = max(dp[j], dp[j-v[i]] + w[i]); 
        
}

   完全背包问题:

    朴素版:(二维数组)

  状态表示:dp[i][j]:从前i个物品中选择且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案

  状态计算:dp[i][j] = max ( dp[i-1][j] , dp[i][j-vi]+wi

    证明:dp[i][j] = max ( dp[i-1][j] , dp[i][j-vi]+w, dp[i][j-2*vi]+2*wi , dp[i][j-3*vi]+3*w, ...... ) .

       dp[i][j-vi] = max (              dp[i-1][j-vi] ,   dp[i][j-2*vi]+w,     dp[i][j-3*vi]+2*w,  ...... ) .

       Thus,dp[i][j-vi] + wi = max ( dp[i-1][j-vi]+wi , dp[i][j-2*vi]+2*w, dp[i][j-3*vi]+3*w,  ...... ) .

       Thus,dp[i][j] = max ( dp[i-1][j] , dp[i][j-vi]+wi ) . 

  核心代码:

int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N][M];

void keyCode()
{
    for(int i = 1; i <= n; i++)
        for(int j = 0; j <= m; j++)
        {
            dp[i][j] = dp[i-1][j];
            if(j >= v[i]) dp[i][j] = max(dp[i][j], dp[i][j-v[i]] + w[i]);
        }
}

    空间优化版:(滚动数组,二维数组优化至一维)

  状态表示:dp[j]:在外循环的第i层时,表示从前i个物品中选择且总体积不超过j的集合的最大价值,n层循环后,dp[m]就是最终答案

  状态计算:dp[j] = max ( dp[j] , dp[j-vi]+wi )  // 由含i和不含i两个子集合计算而来

  核心代码:

int n, m; // n:物品数量, m:最大体积
int v[N], w[N], dp[N];

void keyCode()
{
    for(int i = 1; i <= n; i++)
        // 正向遍历, 使得dp[j-v[i]]为dp[i][j-v[i]]
        for(int j = v[i]; j <= m; j++) 
            dp[j] = max(dp[j], dp[j-v[i]] + w[i]);
        
}

 

标签:updating,int,vi,wi,笔记,max,物品,动态,dp
来源: https://www.cnblogs.com/jakon/p/15861053.html