dp-背包模型
一:01背包问题模型
1 题目:
有一个箱子容量为 V,同时有 n 个物品,每个物品有一个体积(正整数)。
要求 n 个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
第一行是一个整数 V,表示箱子容量。
第二行是一个整数 n,表示物品数。
接下来 n 行,每行一个正整数(不超过10000),分别表示这 n 个物品的各自体积。
输出格式
一个整数,表示箱子剩余空间。
数据范围
<span id="MathJax-Span-2" class="mrow"><span id="MathJax-Span-3" class="mn">0<span id="MathJax-Span-4" class="mo"><<span id="MathJax-Span-5" class="mi">V<span id="MathJax-Span-6" class="mo">≤<span id="MathJax-Span-7" class="mn">200000<V≤20000,
<span id="MathJax-Span-9" class="mrow"><span id="MathJax-Span-10" class="mn">0<span id="MathJax-Span-11" class="mo"><<span id="MathJax-Span-12" class="mi">n<span id="MathJax-Span-13" class="mo">≤<span id="MathJax-Span-14" class="mn">300<n≤30
输入样例:
24
6
8
3
12
7
9
7
输出样例:
0
代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int N = 20010;
5 int dp[N];
6
7 int main(){
8 int V;cin >> V;
9 int n;cin >> n;
10 for(int i = 1;i <= n;++i){
11 int v;cin >> v;
12 for(int j = V;j >= v;--j)
13 dp[j] = max(dp[j], dp[j - v] + v);
14 }
15 cout << V - dp[V];
16 return 0;
17 }
2 数字组合问题
题目:
给定N个正整数<span id="MathJax-Span-2" class="mrow"><span id="MathJax-Span-3" class="msubsup"><span id="MathJax-Span-4" class="mi">A<span id="MathJax-Span-5" class="mn">1<span id="MathJax-Span-6" class="mo">,<span id="MathJax-Span-7" class="msubsup"><span id="MathJax-Span-8" class="mi">A<span id="MathJax-Span-9" class="mn">2<span id="MathJax-Span-10" class="mo">,<span id="MathJax-Span-11" class="mo">…<span id="MathJax-Span-12" class="mo">,<span id="MathJax-Span-13" class="msubsup"><span id="MathJax-Span-14" class="mi">A<span id="MathJax-Span-15" class="mi">NA1,A2,…,AN,从中选出若干个数,使它们的和为M,求有多少种选择方案。
输入格式
第一行包含两个整数N和M。
第二行包含N个整数,表示<span id="MathJax-Span-17" class="mrow"><span id="MathJax-Span-18" class="msubsup"><span id="MathJax-Span-19" class="mi">A<span id="MathJax-Span-20" class="mn">1<span id="MathJax-Span-21" class="mo">,<span id="MathJax-Span-22" class="msubsup"><span id="MathJax-Span-23" class="mi">A<span id="MathJax-Span-24" class="mn">2<span id="MathJax-Span-25" class="mo">,<span id="MathJax-Span-26" class="mo">…<span id="MathJax-Span-27" class="mo">,<span id="MathJax-Span-28" class="msubsup"><span id="MathJax-Span-29" class="mi">A<span id="MathJax-Span-30" class="mi">NA1,A2,…,AN。
输出格式
包含一个整数,表示可选方案数。
数据范围
<span id="MathJax-Span-32" class="mrow"><span id="MathJax-Span-33" class="mn">1<span id="MathJax-Span-34" class="mo">≤<span id="MathJax-Span-35" class="mi">N<span id="MathJax-Span-36" class="mo">≤<span id="MathJax-Span-37" class="mn">1001≤N≤100,
<span id="MathJax-Span-39" class="mrow"><span id="MathJax-Span-40" class="mn">1<span id="MathJax-Span-41" class="mo">≤<span id="MathJax-Span-42" class="mi">M<span id="MathJax-Span-43" class="mo">≤<span id="MathJax-Span-44" class="mn">100001≤M≤10000,
<span id="MathJax-Span-46" class="mrow"><span id="MathJax-Span-47" class="mn">1<span id="MathJax-Span-48" class="mo">≤<span id="MathJax-Span-49" class="msubsup"><span id="MathJax-Span-50" class="mi">A<span id="MathJax-Span-51" class="mi">i<span id="MathJax-Span-52" class="mo">≤<span id="MathJax-Span-53" class="mn">10001≤Ai≤1000
输入样例:
4 4
1 1 2 2
输出样例:
3
代码:
1 #include <iostream>
2 using namespace std;
3
4 const int N = 10010;
5
6 int dp[N];
7 int arr[110];
8
9 int main(){
10 int n, m;cin >> n >> m;
11 for(int i = 1;i <= n;++i)cin >> arr[i];
12 dp[0] = 1;
13 for(int i = 1;i <= n;++i)
14 for(int j = m;j >= arr[i];--j)
15 dp[j] = dp[j] + dp[j-arr[i]];
16 cout << dp[m];
17 }
数字组合问题2:
二:完全背包模型:
1:题目:
小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元。
问小明有多少种买书方案?(每种书可购买多本)
输入格式
一个整数 n,代表总共钱数。
输出格式
一个整数,代表选择方案种数。
数据范围
<span id="MathJax-Span-2" class="mrow"><span id="MathJax-Span-3" class="mn">0<span id="MathJax-Span-4" class="mo">≤<span id="MathJax-Span-5" class="mi">n<span id="MathJax-Span-6" class="mo">≤<span id="MathJax-Span-7" class="mn">10000≤n≤1000
输入样例1:
20
输出样例1:
2
输入样例2:
15
输出样例2:
0
输入样例3:
0
输出样例3:
1
算法分析:
代码:
1 #include <iostream>
2
3 using namespace std;
4
5 const int N = 1010;
6
7 int n;
8 int v[4] = {10, 20, 50, 100};
9 int f[N];
10
11 int main()
12 {
13 cin >> n;
14
15 f[0] = 1;
16 for (int i = 0; i < 4; i ++ )
17 for (int j = v[i]; j <= n; j ++ )
18 f[j] += f[j - v[i]];
19
20 cout << f[n] << endl;
21
22 return 0;
23 }
需要注意的是本题求的是方案数,也就是说手里的钱是必然全部花光的,而求价值的完全背包问题,手里的钱是不一定全部花光的
才用上面的代码定义的dp就是方案数,不会因为这个问题出错
2:稍微有点难度的完全背包问题
题目:
在网友的国度中共有 n 种不同面额的货币,第 i 种货币的面额为 a[i],你可以假设每一种货币都有无穷多张。
为了方便,我们把货币种数为 n、面额数组为 a[1..n] 的货币系统记作 (n,a)。
在一个完善的货币系统中,每一个非负整数的金额 x 都应该可以被表示出,即对每一个非负整数 x,都存在 n 个非负整数 t[i] 满足 a[i]× t[i] 的和为 x。
然而,在网友的国度中,货币系统可能是不完善的,即可能存在金额 x 不能被该货币系统表示出。
例如在货币系统 n=3, a=[2,5,9] 中,金额 1,3 就无法被表示出来。
两个货币系统 (n,a) 和 (m,b) 是等价的,当且仅当对于任意非负整数 x,它要么均可以被两个货币系统表出,要么不能被其中任何一个表出。
现在网友们打算简化一下货币系统。
他们希望找到一个货币系统 (m,b),满足 (m,b) 与原来的货币系统 (n,a) 等价,且 m 尽可能的小。
他们希望你来协助完成这个艰巨的任务:找到最小的 m。
输入格式
输入文件的第一行包含一个整数 T,表示数据的组数。
接下来按照如下格式分别给出T组数据。
每组数据的第一行包含一个正整数 n。
接下来一行包含 n 个由空格隔开的正整数 a[i]。
输出格式
输出文件共有T行,对于每组数据,输出一行一个正整数,表示所有与 (n,a) 等价的货币系统 (m,b) 中,最小的 m。
数据范围
<span id="MathJax-Span-2" class="mrow"><span id="MathJax-Span-3" class="mn">1<span id="MathJax-Span-4" class="mo">≤<span id="MathJax-Span-5" class="mi">n<span id="MathJax-Span-6" class="mo">≤<span id="MathJax-Span-7" class="mn">1001≤n≤100,
<span id="MathJax-Span-9" class="mrow"><span id="MathJax-Span-10" class="mn">1<span id="MathJax-Span-11" class="mo">≤<span id="MathJax-Span-12" class="mi">a<span id="MathJax-Span-13" class="mo">[<span id="MathJax-Span-14" class="mi">i<span id="MathJax-Span-15" class="mo">]<span id="MathJax-Span-16" class="mo">≤<span id="MathJax-Span-17" class="mn">250001≤a[i]≤25000,
<span id="MathJax-Span-19" class="mrow"><span id="MathJax-Span-20" class="mn">1<span id="MathJax-Span-21" class="mo">≤<span id="MathJax-Span-22" class="mi">T<span id="MathJax-Span-23" class="mo">≤<span id="MathJax-Span-24" class="mn">201≤T≤20
输入样例:
2
4
3 19 10 6
5
11 29 13 19 17
输出样例:
2
5
思路分析
1:通过本题明白给定一个数组如何找出数组中除了他自己以外不可以被其他元素(其他元素可以选取的个数是无限的)通过相加的方式得到的数就可以,我们可以想到和完全背包问题相类似,所以我们可以借鉴一下完全背包的思路
2:dp[i] 表示 元素i可以被数组中的元素表示出来的的方案数,如果等于1那么可知改元素符合条件 ,计算求方案数才用和上面的题一样的方法
3:不可以被其他元素表示出来得到的数,一定可以通过某些相加的方式把其他元素表示出来
代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int N = 25010;
5
6 int dp[N];
7 int arr[N];
8
9 int main(){
10 int T;cin >> T;
11 while(T --){
12 int n;cin >> n;
13 for(int i = 1;i <= n;++i) cin >> arr[i];
14
15 sort(arr, arr+1+n);
16
17 int m = arr[n];
18 memset(dp, 0, sizeof dp);
19 dp[0] = 1;// 组成0的方案数是1
20
21 for(int i = 1;i <= n;++i){
22 for(int j = arr[i];j <= m;++j)
23 dp[j] = dp[j] + dp[j-arr[i]];
24 }
25
26 int ans = 0;
27 for(int i = 1;i <= n;++i)
28 if(dp[arr[i]] == 1) ++ans;
29 cout << ans << endl;
30 }
31 return 0;
32 }
dp-背包模型的更多相关文章
- dp表模型-如何写出for循环动态规划
题目很肤浅.. 但是这件事我们要做.. 那么有一种方法叫做刷表法.. 当你发现这个问题具有最优子结构,重叠子问题时 那么这是一个dp问题是使用本方法的前提 画出该dp状态所对应的矩阵 画出转移关系线. ...
- NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索
矩形嵌套 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a& ...
- 【bzoj1688】[USACO2005 Open]Disease Manangement 疾病管理 状态压缩dp+背包dp
题目描述 Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) is running through the farm. Far ...
- 括号序列的dp问题模型
括号序列的dp问题模型 Codeforces314E ◦给定一个长度为n的仅包含左括号和问号的字符串,将问号变成左括号或 右括号使得该括号序列合法,求方案总数. ◦例如(())与()()都是合法的括号 ...
- URAL_1018 Binary Apple Tree 树形DP+背包
这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- HDU 5234 DP背包
题意:给一个n*m的矩阵,每个点是一个蛋糕的的重量,然后小明只能向右,向下走,求在不超过K千克的情况下,小明最终能吃得最大重量的蛋糕. 思路:类似背包DP: 状态转移方程:dp[i][j][k]--- ...
- dp常见模型
1.背包问题.0/1背包.完全背包.多重背包.分组背包.依赖背包. 2.子序列.最长非上升/下降子序列.最长先上升再下降子序列.最长公共子序列.最大连续子区间和. 3.最大子矩阵. 4.区间dp. 5 ...
- HDU4276 The Ghost Blows Light(树形DP+背包)
题目大概说一棵n个结点树,每个结点都有宝藏,走过每条边要花一定的时间,现在要在t时间内从结点1出发走到结点n,问能获得最多的宝藏是多少. 放了几天的题,今天拿出来集中精力去想,还是想出来了. 首先,树 ...
- HDU 4003 (树形DP+背包)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4003 题目大意:有K个机器人,走完树上的全部路径,每条路径有个消费.对于一个点,机器人可以出去再回来 ...
随机推荐
- 【python基础】第01回 计算机基础1
本章内容概要 1.文件路径2.typora主要功能介绍3.typora语法学习(markdown)4.计算机的本质5.计算机五大组成部分6.网络博文编写教程 本章内容详解 1.文件路径 --路径:可以 ...
- python小题目练习(一)
题目:输出1+2+3+4+5+--+100的总数,并打印出这行式子 代码展示:# 1.定义一个初识变量total,用于后面每次循环进行累加值 total = 0# 2.利用for循环遍历累加for i ...
- 阿里云有奖体验:如何通过ECS挂载NAS文件系统
实验简介 本实验提供CentOS系统ECS一台和NAS文件服务. NAS基于POSIX文件接口,天然适配原生操作系统,提供共享访问,同时保证数据一致性和锁互斥.它提供了简单的可扩展文件存储以供与ECS ...
- Solution -「SDOI2011」拦截导弹
Sol. 题目要求一个数对序列的二维最长下降子序列,我们称其为 Q.并求出每一个元素分别在可能的 Q 中出现了多少次. 直接 Dp,时间复杂度 \(O(n^2)\) 不行.考虑 CDQ 分治 ...
- Python3.7将普通图片(png)转换为SVG图片格式并且让你的网站Logo(图标)从此”动”起来
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_148 在之前的几篇文章中,介绍了业界中比较火爆的图片技术SVG(Scalable Vector Graphics),比如Iconf ...
- 【FAQ】【Push Kit】 华为怎么设置角标
[问题描述] HMS Core Push 怎么设置角标?角标设置不成功如何去排查问题? [问题解答] 华为推送怎么设置角标? 1.消息体设置 我们可以参考桌面角标这一篇文档进行设置角标 2.端测 ...
- DolphinScheduler 线上 Meetup 视频回放(07.25)
上周六下午 DolphinScheduler 社区联合 Doris 社区进行了 2020 年首次线上 Meetup,各位讲师都做了非常精彩的分享,也吸引了 1900 多位技术伙伴观看. 其中 Dolp ...
- LuoguP2953 [USACO09OPEN]牛的数字游戏Cow Digit Game(博弈论)
1~9显然,后面平\(A\)过去 #include <iostream> #include <cstdio> #include <cstring> #include ...
- 业界压测平台与JMeter的对比
压测平台是什么? 压测,即压力测试,作用是对各种服务对象进行压力测试以获得该服务处于或超过预期负载时系统的运行情况,进而判断系统在峰值负载或超出最大负载情况下的处理能力. 压测工具,顾名思义,就是用来 ...
- 神器 利器 Typora
用typora编辑真的实在太爽了! gooooooooooooooooooooooooooooooood! 支持html可以实现好看的排版! 支持latex实在是太棒了! 不过默认不支持,要去首选项里 ...