动态规划- 背包问题总结(一)

简介: 动态规划- 背包问题总结(一)

什么是动态规划

动态规划通过额外的空间将已经搜索过的相似的结果(指某些具有相同性质解的集合)用一个数组存起来,所以DP中的状态转移看上去是某两三个值之间的推导,其实是某两三个集合之间的状态转移!

常见的背包模型

  1. 01背包问题
  2. 完全背包问题
  3. 多重背包问题
  4. 分组背包问题

01背包问题

典型题例:

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i 件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值。

示例 :

输入:第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积
     接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值
4 5
1 2
2 4
3 4
4 5

思路

代码:

朴素做法:

#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    for (int i = 1; i <=n; i ++)
        for (int j = 0; j <= m; j ++) {
            f[i][j] = f[i - 1][j];  //所有不选i的集合(左边集合)
            //  当前背包容量装不进第i个物品,则价值等于前i-1个物品
            if (j >= v[i]) f[i][j] = max(f[i][j], f[i -1][j - v[i]] + w[i]);
        }
    cout << f[n][m] << endl;
    return 0;
}

空间优化-等式变形

#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    for (int i = 1; i <= n; i ++) 
        for (int j = m; j >= v[i]; j --) 
            f[j] = max(f[j], f[j - v[i]] + w[i]); 
    cout << f[m] << endl;
    return 0;
}

完全背包问题

典型题例:

有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。

第 i 种物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值。

示例 :

输入:第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
     接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 种物品的体积和价值。
4 5
1 2
2 4
3 4
4 5
输出:
10

思路

代码:

朴素做法

#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
int f[N][N];
int v[N], w[N];
int main(){
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
        cin >> v[i] >> w[i];
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++){
            f[i][j] = f[i -1][j]; //先算前1~i-1
            if (j >= v[i]) 
                f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
        }
    cout << f[n][m] << endl;
    return 0;
}

优化

#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
int f[N];
int v[N], w[N];
int main(){
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
        cin >> v[i] >> w[i];
    for (int i = 1; i <= n; i ++)
        for (int j = v[i]; j <= m; j ++)
                f[j] = max(f[j], f[j - v[i]] + w[i]);
    cout << f[m] << endl;
    return 0;
}

传送门:动态规划- 背包问题总结(二)

充电站

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

相关文章
|
15天前
|
存储 算法
动态规划(背包问题)
动态规划(背包问题)
|
21天前
|
C++
每日练习之——背包问题
每日练习之——背包问题
12 1
|
1月前
|
算法
动态规划—(背包问题)
动态规划—(背包问题)
|
1月前
|
消息中间件 Kubernetes NoSQL
动态规划- 背包问题总结(二)
动态规划- 背包问题总结(二)
|
7月前
|
算法
背包问题之贪心算法
背包问题之贪心算法
58 0
|
10月前
|
存储 算法
动态规划之背包问题
动态规划之背包问题
71 0
动态规划:完全背包问题
动态规划:完全背包问题
60 0
动态规划:多重背包问题
动态规划:多重背包问题
55 0
|
机器学习/深度学习
动态规划-背包问题
动态规划-背包问题