C++ 完全背包时间优化、完全背包空间优化

完全背包时间优化:

状态转移方程:dpij = max(dpi-1j, dpij - c\[i] + wi)

有以下的内容,状态转移与k无关了,状态转移的时间复杂度从O(m)变成了O(1)

对于第i个物品,其实有两种选择,一个都不放,至少放一个。

一个都不放,就是前i-1种物品放满一个容量为j的背包,是dpi-1j

至少放一个的话,我们尝试在"前i个物品放满一个容量为j的背包",拿到一个物品,即前i种物品放满一个容量为j-ci的背包,这个时候便是dpij-c\[i] + wi

代码分析,核心代码

function KnapsackComplete(n, m, cn+1, wn+1, dpn+1m+1)

dp00 = init

for i->(1, m)

dp0i = inf

for i-> (1,n)

for j-> (0, ci-1)

dpij = dpi-1j

for j->(ci, m)

dpij = opt(dpi-1j, dpij-c\[i]+wi)

代码练习 1 对应蓝桥云课 小明的背包2 见下

cpp 复制代码
#include <iostream>
using namespace std;

#define maxn 1001
#define maxv 1001
#define inf -1
#define init 0
#define vType int

vType opt(vType a, vType b){
  if(a == inf) return b;
  if(b == inf) return a;
  return a>b ? a:b;
}
void KnapsackComplete(int n, int V, int w[maxn], vType v[maxv], vType dp[maxn][maxv]){
  for(int i=1; i<=V; ++i){
    dp[0][i] = inf;
  }
  dp[0][0] = init;

  for(int i=1; i<=n; ++i){
    for(int j=0; j<w[i]; ++j){
      dp[i][j] = dp[i-1][j];
    }
    for(int j=w[i]; j<=V; ++j){
      dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]] + v[i]);
    }
  }
}

int n, V;
int w[maxn];
vType v[maxn];
vType dp[maxn][maxv];

int main()
{
  cin >> n >> V;
  for(int i=1; i<=n; ++i){
    cin >> w[i] >> v[i];
  }
  KnapsackComplete(n, V, w, v, dp);
  int ans = inf;
  for(int i=0; i <= V; ++i){
    ans = max(ans, dp[n][i]);
  }
  cout << ans << endl;
  // 请在此输入您的代码
  return 0;
}

完全背包空间优化,公式见下

dpj = max(dpj, dpj - c\[i] + wi)

代码分析:

核心代码,

function KnapsackComplete(n, m, cn+1, wn+1, dpm+1)

dp0 = init

for i->(1, m)

dpi = inf

for i-> (1,n)

for j-> (ci, m)

dpj = opt(dpj, dpj-c\[i]+wi)

代码练习 1 对应蓝桥云课 小明的背包2 代码见下

cpp 复制代码
#include <iostream>
using namespace std;

#define maxn 1001
#define maxv 1001
#define inf -1
#define init 0
#define vType int

vType opt(vType a, vType b){
  if(a == inf) return b;
  if(b == inf) return a;
  return a>b ? a:b;
}
void KnapsackComplete(int n, int V, int w[maxn], vType v[maxv], vType dp[maxv]){
  dp[0] = init;

  for(int i=1; i<=V; ++i){
    dp[i] = inf;
  }
  for(int i=1; i<=n; ++i){
    for(int j=w[i]; j<=V; ++j){
      dp[j] = opt(dp[j], dp[j-w[i]]+v[i]);
    }
  }
}

int n, V;
int w[maxn];
vType v[maxn];
vType dp[maxv];

int main()
{
  cin >> n >> V;
  for(int i=1; i<=n; ++i){
    cin >> w[i] >> v[i];
  }
  KnapsackComplete(n, V, w, v, dp);
  int ans = inf;
  for(int i=0; i <= V; ++i){
    ans = max(ans, dp[i]);
  }
  cout << ans << endl;
  // 请在此输入您的代码
  return 0;
}

代码练习2 对应力扣硬币 代码见下

cpp 复制代码
#define maxn 5
#define maxv 1000001
#define inf 0
#define init 1
#define vType int

vType opt(vType a, vType b){
  if(a == inf) return b;
  if(b == inf) return a;
  return (a+b)%1000000007;
}
void KnapsackComplete(int n, int V, int w[maxn], vType v[maxv], vType dp[maxv]){
  dp[0] = init;

  for(int i=1; i<=V; ++i){
    dp[i] = inf;
  }
  for(int i=1; i<=n; ++i){
    for(int j=w[i]; j<=V; ++j){
      dp[j] = opt(dp[j], dp[j-w[i]]+v[i]);
    }
  }
}

int n, V;
int w[maxn] = {-1, 25, 10, 5, 1};
vType v[maxn] = {-1, 0, 0, 0, 0};
vType dp[maxv];

class Solution {
public:
    int waysToChange(int n) {
        KnapsackComplete(4, n, w, v, dp);
        return dp[n];
    }
};
相关推荐
Evand J1 小时前
【MATLAB例程介绍】(17)永磁同步电机(PMSM)基于自适应无迹卡尔曼滤波(AUKF)的电流噪声在线估计。测量噪声协方差自适应与转速估计对比仿真
开发语言·matlab·卡尔曼滤波·无迹卡尔曼滤波·pmsm·电机滤波
BaiPeter2 小时前
ZPL文件预览
开发语言·c++
小此方4 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん5 小时前
【C++】哈希表
c++·算法·散列表
Severus_black7 小时前
【C++初阶】list使用及相关实现,思路顺滑流畅!
c语言·数据结构·c++·stl·list
噢,我明白了7 小时前
JAVA中的一些基础应用知识点
java·开发语言
时间的拾荒人8 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾9 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
码途行者10 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
旖旎夜光10 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习