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个机器人,走完树上的全部路径,每条路径有个消费.对于一个点,机器人可以出去再回来 ...
 
随机推荐
- RPA应用场景-自动轮询汇总报表
			
场景概述 自动轮询汇总报表 所涉系统名称 券商披露网站 人工操作(时间/次) 36小时 所涉人工数量 1 操作频率 每月 场景流程 1.每月初机器人自动登录网站轮询36家券商披露的财务报告,并下载 2 ...
 - UiPath文本操作Get Full Text的介绍和使用
			
一.Get Full Text操作的介绍 使用Get Full Text(获取全文本 )屏幕抓取方法从指示的UI元素中提取字符串及其信息 二.Get Full Text在UiPath中的使用 1. 打 ...
 - Java方法读取文件内容
			
一.针对文件内容的读取,在平时的工作中想必是避免不了的操作,现在我将自己如何用java方法读取文件中内容总结如下:废话不多说,直接上代码: 1 public static void main(Stri ...
 - 编译调试Net6源码
			
前言 编辑调试DotNet源码可按照官网教程操作,但因为网络问题中间会出现各种下载失败的问题,这里出个简单的教程(以6为版本) 下载源码 下载源码 GitHub下载源码速度极慢,可替换为国内仓库htt ...
 - NC23036 华华听月月唱歌
			
NC23036 华华听月月唱歌 题目 题目描述 月月唱歌超级好听的说!华华听说月月在某个网站发布了自己唱的歌曲,于是把完整的歌曲下载到了U盘里.然而华华不小心把U盘摔了一下,里面的文件摔碎了.月月的歌 ...
 - 智能指针思想实践(std::unique_ptr, std::shared_ptr)
			
1 smart pointer 思想  个人认为smart pointer实际上就是一个对原始指针类型的一个封装类,并对外提供了-> 和 * 两种操作,使得其能够表现出原始指针的操作行为.  ...
 - 一个思维导图,带你深入理解 Linux 网络
			
说明 思维导图 目录 内核接收网络包 内核与用户进程协作 内核发送网络包 TCP 连接 网络性能优化 GitHub 项目 说明 经朋友推荐发现一本好书:<深入理解 Linux 网络>,本文 ...
 - MATLAB复习资料——浙商大管工学院适用
			
包含12套复习卷,课堂PPT 下载链接:MATLAB练习模拟题库(12套).pdf - 蓝奏云 (lanzoub.com)
 - SpringBoot数据库管理 - 用flyway对数据库管理和迁移
			
上文介绍了Liquibase,以及和SpringBoot的集成.除了Liquibase之外,还有一个组件Flyway也是经常被使用到的类似的数据库版本管理中间件.本文主要介绍Flyway, 以及Spr ...
 - DDS信号发生器加强版(双通道,发送波形的频率可控,相位可控,种类可控)
			
目的:设计一个DDS,可以输出两个波形,输出的波形的周期可以修改,相位可以修改,种类也可以修改 输入:clk,reset,一个控制T的按键,一个控制相位的按键,一个控制波形种类的按键. 思路:双通道- ...
 
			
		