【动态规划】三种基本背包问题
2018-03-24 22:15
417 查看
动态规划 是对解最优化问题的一种途径 它往往是针对一种最优化问题 根据问题的不同性质 确定不同的设计方法
因为这篇文章我想说点关于背包问题的事情 所以不再过多介绍动态规划
背包问题 是动态规划中的一个经典题型 在联赛中也经常出现 其基本问题主要分为01 完全 多重 三种
下面就通过程序与例题分别来说一下三种基本问题
特点 这是最简单的背包问题 特点是每个物品只有一件供你选择放还是不放
对于这个问题一般有两种解法 下面分别来介绍一下
① 二维解法
设f[i][j]表示前i件物品 总重量不超过j的最大价值 可得出状态转移方程
f[i][j]=max{f[i-1][j-a[i]]+b[i],f[i-1][j]}
代码如下
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[/code]
虽然“原理”没有错 但是f数组开的太大 (一般应该5000就顶头了)
在一些情况下 题目的数据会很大 因此f数组不开到一定程度是没有办法ac的 那么该怎么办呢 于是
②一维解法
设f[j]表示重量不超过j公斤的最大价值 可得出状态转移方程
fj=maxj{fj,f[j−a[i]]+b[i]}” role=”presentation” style=”text-align: center; position: relative;”>fj=maxj{fj,f[j−a[i]]+b[i]}fj=maxj{fj,f[j−a[i]]+b[i]}
代码如下
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[/code]
这样用一维数组代替二维数组就解决了很多问题 所以用一维数组解决01背包是很重要的
01背包的例题有:[USACO07DEC]手链Charm Bracelet(洛谷搜索 P2871) 采药(洛谷搜索 P1048) [Noip普及组2001]装箱问题(洛谷搜索 P1049)
特点 题干看似与01一样 但它的特点是每个物品可以无限选用
其实这个题也可以写二维和一维两种 但之前已经说过了二维的有一定局限 所以在此之介绍一维
一维
设f[j]表示重量不超过j公斤的最大价值 可得出状态转移方程
fj=maxj{fj,f[j−a[i]]+b[i]}” role=”presentation” style=”text-align: center; position: relative;”>fj=maxj{fj,f[j−a[i]]+b[i]}fj=maxj{fj,f[j−a[i]]+b[i]}
代码如下
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[/code]
大家有没有感觉代码很熟悉?每错 一维完全背包的代码与一维01背包的代码只在循环上有些差别 而且状态转移方程也一样
例题可以百度搜索收益(也叫投资)
算了好人做到底我还是ctrl+v一下题目吧
【题目描述】收益 (POJ 2063)
“建太空梯进入太空要1兆亿?”魔法学院的院长瞪大了眼睛。
“这只是基础设施的费用,后期还要……”墨老师掰着手指算。
“哎呀,现在地主也很穷啊,学院的钱批下来就这么多,你想办法用这笔钱在债券市场上获得最大收益吧。”院长皱着眉头。
简单来说,就是你有一笔钱,你要将这笔钱去投资债券,现在有d种债券,每种债券都有一个价值和年收益,债券的价值是1000的倍数,问你如何投资在n年后的获得最大收益。
【输入格式】
第一个为一个整数M,表示有M组数据。
每组数据第一行有两个整数,表示初始资金(不超过50000)和年数n。
每组数据第二行为一个整数d(1 ≤ d≤10),表示债券种类。
随后d行每行有两个整数,表示该债券的价值和年收益。年收益不会超过债券价值的10%。
所有数据不超过整型取值范围。
【输出格式】
每组数据,输出n年后获得的最大收益。
【输入样例】
1
10000 4
2
4000 400
3000 250
【输出样例】
14050
贴一下我这个题的代码
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[/code]
特点 它与完全背包有类似点 特点是每个物品都有了一定的数量
状态转移方程为:
f[j]=max{f[j],f[j−k∗a[i]]+k∗b[i]}” role=”presentation” style=”text-align: center; position: relative;”>f[j]=max{f[j],f[j−k∗a[i]]+k∗b[i]}f[j]=max{f[j],f[j−k∗a[i]]+k∗b[i]}
【输入样例】
8 2
2 100 4
4 100 2
【输出样例】
400
代码如下
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[/code]
这是一种简单的朴素算法 多重背包有常见的二进制优化转为01背包 以后会提到
这就是常见的三种基本背包问题 之后将会借助 【Noip普及组2001】装箱问题
来展现一下动态规划与贪心算法的联系
文章写的不好,继续努力!!
//COYG
转自:https://blog.csdn.net/qq_36303472/article/details/68935954
因为这篇文章我想说点关于背包问题的事情 所以不再过多介绍动态规划
背包问题 是动态规划中的一个经典题型 在联赛中也经常出现 其基本问题主要分为01 完全 多重 三种
下面就通过程序与例题分别来说一下三种基本问题
01背包
有n件物品和容量为m的背包 给出i件物品的重量以及价值 求解让装入背包的物品重量不超过背包容量 且价值最大特点 这是最简单的背包问题 特点是每个物品只有一件供你选择放还是不放
对于这个问题一般有两种解法 下面分别来介绍一下
① 二维解法
设f[i][j]表示前i件物品 总重量不超过j的最大价值 可得出状态转移方程
f[i][j]=max{f[i-1][j-a[i]]+b[i],f[i-1][j]}
代码如下
#include<iostream> using namespace std; int main() { int m,n; cin>>n>>m; int a[50001],b[50001]; int f[5001][5001]; for(int i=1;i<=n;i++)cin>>a[i]>>b[i]; for(int i=1;i<=n;i++) for(int j=m;j>0;j--){ if(a[i]<=j)f[i][j]=max(f[i-1][j],f[i-1][j-a[i]]+b[i]); else f[i][j]=f[i-1][j]; } cout<<f [m]<<endl; //最优解 //COYG }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[/code]
虽然“原理”没有错 但是f数组开的太大 (一般应该5000就顶头了)
在一些情况下 题目的数据会很大 因此f数组不开到一定程度是没有办法ac的 那么该怎么办呢 于是
②一维解法
设f[j]表示重量不超过j公斤的最大价值 可得出状态转移方程
fj=maxj{fj,f[j−a[i]]+b[i]}” role=”presentation” style=”text-align: center; position: relative;”>fj=maxj{fj,f[j−a[i]]+b[i]}fj=maxj{fj,f[j−a[i]]+b[i]}
代码如下
#include<iostream> using namespace std; int main() { int n,m; cin>>n>>m; int a[50001],b[50001]; for(int i=1;i<=n;i++)cin>>a[i]>>b[i]; int f[50001]={0}; for(int i=1;i<=n;i++){ f 4000 or(int j=m;j>=a[i];j--) if(f[j-a[i]]+b[i]>f[j])f[j]=f[j-a[i]]+b[i]; } cout<<f[m]<<endl; //最优解 //COYG }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[/code]
这样用一维数组代替二维数组就解决了很多问题 所以用一维数组解决01背包是很重要的
01背包的例题有:[USACO07DEC]手链Charm Bracelet(洛谷搜索 P2871) 采药(洛谷搜索 P1048) [Noip普及组2001]装箱问题(洛谷搜索 P1049)
完全背包
有n件物品和容量为m的背包 给出i件物品的重量以及价值 求解让装入背包的物品重量不超过背包容量 且价值最大特点 题干看似与01一样 但它的特点是每个物品可以无限选用
其实这个题也可以写二维和一维两种 但之前已经说过了二维的有一定局限 所以在此之介绍一维
一维
设f[j]表示重量不超过j公斤的最大价值 可得出状态转移方程
fj=maxj{fj,f[j−a[i]]+b[i]}” role=”presentation” style=”text-align: center; position: relative;”>fj=maxj{fj,f[j−a[i]]+b[i]}fj=maxj{fj,f[j−a[i]]+b[i]}
代码如下
#include<iostream> using namespace std; int main() { int n,m; cin>>n>>m; int a[50001],b[50001]; int f[50001]={0}; for(int i=1;i<=n;i++){ cin>>a[i]>>b[i]; } for(int i=1;i<=n;i++) for(int j=a[i];j<=m;j++){ if(f[j-a[i]]+b[i]>f[j])f[j]=f[j-a[i]]+b[i]; } cout<<f[m]<<endl;//最优解 //COYG }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[/code]
大家有没有感觉代码很熟悉?每错 一维完全背包的代码与一维01背包的代码只在循环上有些差别 而且状态转移方程也一样
例题可以百度搜索收益(也叫投资)
算了好人做到底我还是ctrl+v一下题目吧
【题目描述】收益 (POJ 2063)
“建太空梯进入太空要1兆亿?”魔法学院的院长瞪大了眼睛。
“这只是基础设施的费用,后期还要……”墨老师掰着手指算。
“哎呀,现在地主也很穷啊,学院的钱批下来就这么多,你想办法用这笔钱在债券市场上获得最大收益吧。”院长皱着眉头。
简单来说,就是你有一笔钱,你要将这笔钱去投资债券,现在有d种债券,每种债券都有一个价值和年收益,债券的价值是1000的倍数,问你如何投资在n年后的获得最大收益。
【输入格式】
第一个为一个整数M,表示有M组数据。
每组数据第一行有两个整数,表示初始资金(不超过50000)和年数n。
每组数据第二行为一个整数d(1 ≤ d≤10),表示债券种类。
随后d行每行有两个整数,表示该债券的价值和年收益。年收益不会超过债券价值的10%。
所有数据不超过整型取值范围。
【输出格式】
每组数据,输出n年后获得的最大收益。
【输入样例】
1
10000 4
2
4000 400
3000 250
【输出样例】
14050
贴一下我这个题的代码
#include<iostream> #include<cstring> using namespace std; int main() { int m,y,n,d,ans=0,a[100001],b[100001]; int f[100001]={0}; cin>>m; while(m--){ cin>>y>>n; cin>>d; for(int i=1;i<=d;i++){ cin>>a[i]>>b[i]; } for(int o=1;o<=n;o++){ for(int i=1;i<=d;i++) for(int j=a[i];j<=y;j++){ f[j]=max(f[j-a[i]]+b[i],f[j]); } y+=f[y]; //每次都要累计 memset(f,0,sizeof(f)); } cout<<y<<endl; } return 0; } //小蒟蒻代码丑 //COYG1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[/code]
多重背包
有n件物品和容量为m的背包 给出i件物品的重量以及价值 还有数量 求解让装入背包的物品重量不超过背包容量 且价值最大特点 它与完全背包有类似点 特点是每个物品都有了一定的数量
状态转移方程为:
f[j]=max{f[j],f[j−k∗a[i]]+k∗b[i]}” role=”presentation” style=”text-align: center; position: relative;”>f[j]=max{f[j],f[j−k∗a[i]]+k∗b[i]}f[j]=max{f[j],f[j−k∗a[i]]+k∗b[i]}
【输入样例】
8 2
2 100 4
4 100 2
【输出样例】
400
代码如下
#include<iostream> using namespace std; int main() { int m,n; cin>>m>>n; int a[10001],b[10001],c[10001]; for(int i=1;i<=n;i++){ cin>>a[i]>>b[i]>>c[i]; } int f[10001]; for(int i=1;i<=n;i++) for(int j=m;j>=0;j--) for(int k=0;k<=c[i];k++){ < b7f7 span class="hljs-keyword">if(j-k*a[i]<0)break; f[j]=max(f[j],f[j-k*a[i]]+k*b[i]); } cout<<f[m]<<endl;//最优解 } //COYG1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[/code]
这是一种简单的朴素算法 多重背包有常见的二进制优化转为01背包 以后会提到
这就是常见的三种基本背包问题 之后将会借助 【Noip普及组2001】装箱问题
来展现一下动态规划与贪心算法的联系
文章写的不好,继续努力!!
//COYG
转自:https://blog.csdn.net/qq_36303472/article/details/68935954
相关文章推荐
- 【动态规划】三种基本背包问题
- 编程算法 - 背包问题(三种动态规划) 代码(C)
- 编程算法 - 背包问题(三种动态规划) 代码(C)
- 编程算法 - 背包问题(三种动态规划) 代码(C)
- 动态规划求解01背包相关的基本问题
- 0/1背包问题(动态规划)
- (背包问题)杭电2602Bone Collector--动态规划入门
- 0-1背包问题的两种解法(回溯法和动态规划)
- 动态规划解决0/1背包问题
- 【笔记】【算法学习】【动态规划】背包问题总结(1)
- 0-1背包问题,用滚动数组,动态规划解决
- 动态规划第二讲——完全背包与多重背包问题
- 【动态规划(三)】经典背包问题
- 背包问题基础(三种背包)
- 物件捆绑 背包问题 动态规划 求解
- 动态规划 背包问题
- 《算法导论》第15章-动态规划之0-1背包问题
- 动态规划-背包问题、兑换零钱问题、旅行商问题
- 动态规划--背包问题
- 01背包问题 动态规划 c语言实现