1.先放上0-1背包模板

二维数组

  1. for(int i=1;i<=n;i++)//枚举 物品
  2. for(int j=1;j<=V;j++)//枚举体积
  3. //这个位置是可以正序枚举的. qwq
  4. //一维01背包必须倒叙 emmm
  5. //这个没错a emmm
  6. if(j>=c[i])
  7. f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);//状态转移方程.
  8. else f[i][j]=f[i-1][j].

滚动二维数组

  1. int dp[2][10010];
  2. int row = 0; //滚动
  3. for (int i = 1; i < n; ++i) {
  4. row = 1 - row;
  5. for (int j = 1; j <= i * (i + 1) / 2; ++j) {//这里可以减少枚举
  6. if(j>=c[i])
  7. f[row][j]=max(f[1-row][j],f[1-row][j-c[i]]+w[i]);//状态转移方程.
  8. else f[row][j]=f[1-row][j].
  9. }
  10. }

一维数组(逆序)

  1. for(int i=1;i<=n;i++)//枚举 物品
  2. for(int j=V;j>=c[i];j--)//枚举体积
  3. f[j]=max(f[j],f[j-c[i]]+w[i]);//状态转移方程.

模板题:洛谷:P1048采药

“采药”这道题套模板就行了,从二维到一维优化。

2.顺便再复习记忆化搜索洛谷:P1048采药记忆化搜索做法题解

先想到dfs搜索暴力解题,就是多参数递归,出口记录搜索到的值

再想到记忆化搜索,什么时记忆化搜索?记录每一次dfs答案,免去重复计算,从而起到优化时间复杂度的作用

记忆化搜索记录什么值呢?记录每次搜索结束找到的价值(不一定最大)



如何想到可以用记忆化搜索?

3.蓝桥杯考过的记忆化搜索——2013年C++B组第9题地宫取宝

使用四维数组缓存记录。

4.蓝桥杯考过的0-1背包:2014年C++A组第十题-波动数列

这道题比较难想到0-1背包,选数字对应成拿物品填充背包,dp[i][j]表示用前i个数凑出数字j的方案数,类似题目:我记得有一道选几个数字,凑出数字n。初始化dp[0][0] = 1,第0列都等于1,dp[i~n][0] = 1

5.完全背包

与0-1背包略有不同的是,每种物品有无限多个,可重复选取。

二维数组,三层循环模板

  1. for(int i=1;i<=n;i++)//枚举物品
  2. for(int j=1;j<=V;j++)
  3. for(int k=1;k<=V/c[i];k++)//我们的物品最多只能放多少件.
  4. {
  5. if(k*c[i]<=j)
  6. f[i][j]=max(f[i-1][j],f[i-1][j-k*c[i]]+k*w[i]);
  7. else
  8. f[i][j]=f[i-1][j];
  9. //判断条件与01背包相同.
  10. }

一维数组,两层循环模板(顺序枚举,和0-1背包一维恰好相反)

  1. for(int i=1;i<=n;i++)//枚举物品
  2. for(int j=c[i];j<=V;j++)//枚举体积.注意这里是顺序/
  3. f[j]=max(f[j],f[j-c[i]]+w[i]);//状态转移.

完全背包模板题:P1616 疯狂的采药

6.蓝桥杯考过的完全背包:2017年蓝桥杯-包子凑数

1~100000(比较大的值)

初始化dp[0] = 1

完全背包思想,推出布尔类型的dp数组,最后遍历最后dp数组最后一层为true的个数

整数划分(每个数可以用无限次)——完全背包

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 100005;
  4. int n;
  5. int dp[maxn];
  6. int main(){
  7. cin>>n;
  8. dp[0] = 1;
  9. for(int i=1;i<=n;i++){//可以用到n
  10. for(int j=i;j<=n;j++){//完全背包 每个数字可以用无限次
  11. dp[j] = dp[j] + dp[j-i];
  12. }
  13. }
  14. cout<<dp[n]<<endl;
  15. return 0;
  16. }

整数划分(每个数只能用一次)——0-1背包

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 100005;
  4. int n;
  5. int dp[maxn];
  6. int main(){
  7. cin>>n;
  8. dp[0] = 1;
  9. for(int i=1;i<=n-1;i++){//不能用n
  10. for(int j=n;j>=i;j--){//0-1背包 倒序
  11. dp[j] = dp[j] + dp[j-i];
  12. }
  13. }
  14. cout<<dp[n]<<endl;
  15. return 0;
  16. }
  17. //输入6
  18. //输出3 说明:1、5;2、4;1、2、3

7.多重背包,没做过题不好讲复习。。

多重背包问题限定了一种物品的个数,一个简单的方法,转成0-1背包。先这样写吧

  1. #include <iostream>
  2. using namespace std;
  3. #define V 1000
  4. int weight[50 + 1];
  5. int value[50 + 1];
  6. int num[20 + 1];
  7. int f[V + 1];
  8. int max(int a, int b) {
  9. return a > b ? a : b;
  10. }
  11. int main() {
  12. int n, m;
  13. cout << "请输入物品个数:";
  14. cin >> n;
  15. cout << "请分别输入" << n << "个物品的重量、价值和数量:" << endl;
  16. for (int i = 1; i <= n; i++) {
  17. cin >> weight[i] >> value[i] >> num[i];
  18. }
  19. int k = n + 1;
  20. for (int i = 1; i <= n; i++) {
  21. while (num[i] != 1) {
  22. weight[k] = weight[i];
  23. value[k] = value[i];
  24. k++;
  25. num[i]--;
  26. }
  27. }
  28. cout << "请输入背包容量:";
  29. cin >> m;
  30. for (int i = 1; i <= k; i++) {
  31. for (int j = m; j >= 1; j--) {
  32. if (weight[i] <= j) f[j] = max(f[j], f[j - weight[i]] + value[i]);
  33. }
  34. }
  35. cout << "背包能放的最大价值为:" << f[m] << endl;
  36. }

学长的dp:https://blog.csdn.net/o_ohello/article/details/89378697

dp小结|背包问题的更多相关文章

  1. 【dp】 背包问题

    问题一:01背包 题目: [题目描述] 一个旅行者有一个最多能装 M 公斤的背包,现在有 n件物品,它们的重量分别是W1,W2,...,Wn它们的价值分别为C1,C2,...,Cn求旅行者能获得最大总 ...

  2. 动态规划(DP),0-1背包问题

    题目链接:http://poj.org/problem?id=3624 1.p[i][j]表示,背包容量为j,从i,i+1,i+2,...,n的最优解. 2.递推公式 p[i][j]=max(p[i+ ...

  3. Codeforces Round #105 (Div. 2) E. Porcelain —— DP(背包问题)

    题目链接:http://codeforces.com/problemset/problem/148/E E. Porcelain time limit per test 1 second memory ...

  4. 「10.19」最长不下降子序列(DP)·完全背包问题(spfa优化DP)·最近公共祖先(线段树+DFS序)

    我又被虐了... A. 最长不下降子序列 考场打的错解,成功调了两个半小时还是没A, 事实上和正解的思路很近了,只是没有想到直接将前$D$个及后$D$个直接提出来 确实当时思路有些紊乱,打的时候只是将 ...

  5. [动态规划]状态压缩DP小结

     1.小技巧 枚举集合S的子集:for(int i = S; i > 0; i=(i-1)&S) 枚举包含S的集合:for(int i = S; i < (1<<n); ...

  6. 概率dp小结

    好久之前学过,记得是一次亚洲区的前几天看了看概率dp,然后亚洲区就出了一道概率dp,当时虽然做上了,但是感觉有很多地方没懂,今天起早温习了一下,觉得很多地方茅塞顿开,果然学习的话早上效果最好了. 首先 ...

  7. 状压DP小结

    看了一个多星期状压DP,总算有点明白,大概可以分为两种:数据是在矩阵中的,数据是线性的,在矩阵中的一般就是排兵布阵这一种的,还有一种线性结构中给定条件让你求最大权值,比如求最大权值路线,TSP问题等, ...

  8. 状态压缩dp小结

    最近一段时间算是学了一些状态压缩的题目,在这里做个小结吧 首先是炮兵布阵类题目,这类题目一开始给定一个矩形,要求在上面放置炮兵,如果在一格放了炮兵那么周围的某些格子就不能放炮兵,求最大能放置炮兵的数量 ...

  9. 数位dp小结

    数位dp其实就是一种用来求区间[l, r]满足条件的数的个数.数位是指:个十百千万,而在这里的dp其实相当于暴力枚举每一位数. 我们通过把l, r的每位数分解出来,然后分别求r里满足条件的数有多少,l ...

随机推荐

  1. 原生js实现图片轮播效果

    思路:设置父容器(一定宽度,一定高度,相对定位,子容器超出部分进行隐藏),子容器图片并排(浮动,绝对定位,每次点击进行相应的左或右偏移量) 1.html: <!DOCTYPE html> ...

  2. 师大校赛D coloring Game 并查集

    这题说的是 在一个 森林中 两个人在这棵树上涂颜色,黑色或者白色,第一次只能在1 号节点上涂色 第二次 只能在2上涂,以此类推, 在每个节点上只能涂黑色或者白色,并且相邻的点不能有相同的颜色,最后求不 ...

  3. uva 1322 Minimizing Maximizer

    题意: 有n个数,m个排序器,每个排序器可以把区间ai到bi的数从小到大排序.这m个排序器的输出就是m个排序之后的第n个数. 现在发现有些排序器是多余的.问至少需要多少个排序器可以使得输出不变.排序器 ...

  4. wifi pj WiFiPhisher 安装使用

    1.安装kali linux: https://blog.csdn.net/qq_42545206/article/details/82788119 https://www.kali.org/down ...

  5. jfinal 项目 控制层、ORM层、AOP层,在发表之前一定要记得保存

    一.ORM简介 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术.简单的说,ORM是通过使用描述对象和数据 ...

  6. spring boot: ConfigurationProperties

    读取配置信息 1.5 之前 @Component @ConfigurationProperties(prefix = "user", locations= {"class ...

  7. Hive 的排名和跨行 窗口函数及其使用

    一.排序&去重分析 row_number() over(partititon by col1 order by col2) as rn 也可以用 row_number() over(distr ...

  8. 20165215 实验一 Java开发环境的熟悉

    20165215 实验一 Java开发环境的熟悉 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:张家佳 学号:20165215 指导教师:娄嘉鹏 实验日期:2018年4月2日 实验 ...

  9. Elasticsearch集群内的原理

        一个运行中的 Elasticsearch 实例称为一个 节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力.当有节点加入集群中或者从 ...

  10. 可视化的fineBI很高大上 使用简单,简单操作了一下,拖一拖就行,收费 只能看一下人家的demo 网站 http://demo.finebi.com/webroot/decision#directory