算法模板:动态规划之完全背包

简介: 算法模板:动态规划之完全背包

前言


唤我沈七就好啦。


往期系列文章

动态规划之01背包


完全背包


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


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


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

输出最大价值。


完全背包与01背包的区别就是每种物品都有无限件可用。


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

递推优化


我们列举一下更新次序的内部关系:

f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w , f[i-1,j-2v]+2w …)

f[i , j-v] = max( f[i-1,j-v] , f[i-1,j-2*v] + w …)

由上两式,可得出如下递推关系:

f[i][j]=max(f[i][j-v]+w , f[i-1][j])


降维优化


有了上面的关系,那么其实k循环可以不要了,核心代码优化成这样:

f[j] = max(f[j-v]+w , f[j])


最终代码


#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int dp[N];
int v[N],w[N];
int main()
{
    int n,m;
    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 ++)
    //完全背包不需要改变遍历顺序
    //这也是优化后完全背包与01背包的区别
    {
        dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
    }
    cout<<dp[m];
    return 0;
}


奶牛的干草


约翰的干草库存已经告罄,他打算为奶牛们采购 H(1≤H≤50000) 磅干草。


他知道 N(1≤N≤100) 个干草公司,现在用 1 到 N 给它们编号。第 i 公司卖的干草包重量为 Pi(1≤Pi≤5,000) 磅,需要的开销为 Ci(1≤Ci≤5,000)美元。每个干草公司的货源都十分充足, 可以卖出无限多的干草包。


帮助约翰找到最小的开销来满足需要,即采购到至少 H 磅干草。


分析:本题是要找最小值,所以dp数组需要初始化成一个很大的数。


坑点:本题要求是在到达重量要求后,所需价值最小,

由于每个公司的价格不同,所以并不是恰好达到重量后花费最小。

所以需要再遍历一遍所有达到要求重量要求的方案,找到其中的最小值。


#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long dp[N],ans=9999999;
long long v[N],w[N],m,n;
int main()
{
  cin>>n>>m;
  for(int i = 1 ; i <= m +5000; i ++)
  dp[i]=1e9;
  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+5000;j ++)
  {
  dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
  }
  for(int i = m ; i <= m+5000; i ++ )
  ans=min(dp[i],ans);
  cout<<ans;
  return 0; 
}


综合应用


神奇的四次方数


将一个整数m分解为n个四次方数的和的形式,要求n最小。例如,m=706,706=54+34,则n=2。


每个数可以用多次。


706


2


题解部分:


每个数可以用多次。


这句话是我加的,我用01背包做了半天。。。


1.因为要求是最小值,所以 d p数组应该初始化为正无穷。


2.为了使d p数组有意义 需要让d p[0] = 0


#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int dp[N],n;
int main()
{
  cin>>n;
  memset(dp,0x3f,sizeof(dp));
  dp[0]=0;
  for(int i = 1;  i <= 20 ; i ++)
  for(int j =i*i*i*i;j <= n ; j ++)
  {
  dp[j]=min(dp[j],dp[j-i*i*i*i]+1);
  }
  cout<<dp[n];
  return 0;
}


完结散花


ok以上就是对 动态规划之完全背包 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。


参考文献


https://www.acwing.com/activity/content/19/


相关文章
|
1月前
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
|
2月前
|
算法 开发者 Python
惊呆了!Python算法设计与分析,分治法、贪心、动态规划...这些你都会了吗?不会?那还不快来学!
【7月更文挑战第10天】探索编程巅峰,算法至关重要。Python以其易读性成为学习算法的首选。分治法,如归并排序,将大问题拆解;贪心算法,如找零问题,每步求局部最优;动态规划,如斐波那契数列,利用子问题解。通过示例代码,理解并掌握这些算法,提升编程技能,面对挑战更加从容。动手实践,体验算法的神奇力量吧!
60 8
|
2月前
|
算法 Python
算法不再难!Python分治法、贪心、动态规划实战解析,轻松应对各种算法挑战!
【7月更文挑战第8天】掌握Python算法三剑客:分治、贪心、动态规划。分治如归并排序,将大问题拆解递归解决;贪心策略在每步选最优解,如高效找零;动态规划利用子问题解,避免重复计算,解决最长公共子序列问题。实例展示,助你轻松驾驭算法!**
50 3
|
1月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
1月前
|
算法 Java 测试技术
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
这篇文章介绍了基于动态规划法的三种算法:解决背包问题的递归和自底向上实现、Warshall算法和Floyd算法,并提供了它们的伪代码、Java源代码实现以及时间效率分析。
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
|
2月前
|
算法 Python
Python算法高手进阶指南:分治法、贪心算法、动态规划,掌握它们,算法难题迎刃而解!
【7月更文挑战第10天】探索Python算法的精华:分治法(如归并排序)、贪心策略(如找零钱问题)和动态规划(解复杂问题)。通过示例代码揭示它们如何优化问题解决,提升编程技能。掌握这些策略,攀登技术巅峰。
62 2
|
2月前
|
算法 程序员 Python
算法小白到大神的蜕变之路:Python分治法、贪心、动态规划,一步步带你走向算法巅峰!
【7月更文挑战第9天】探索算法之旅,以Python解锁编程高手之路。分治法如二分查找,将复杂问题拆解;贪心算法解决活动选择,每次选取局部最优;动态规划求斐波那契数列,避免重复计算,实现全局最优。每一步学习,都是编程能力的升华,助你应对复杂挑战,迈向算法大师!
34 1
|
2月前
|
存储 算法 Python
Python算法界的秘密武器:分治法巧解难题,贪心算法快速决策,动态规划优化未来!
【7月更文挑战第9天】Python中的分治、贪心和动态规划是三大关键算法。分治法将大问题分解为小问题求解,如归并排序;贪心算法每步选局部最优解,不保证全局最优,如找零钱;动态规划存储子问题解求全局最优,如斐波那契数列。选择合适算法能提升编程效率。
49 1
|
2月前
|
存储 算法 Python
震撼!Python算法设计与分析,分治法、贪心、动态规划...这些经典算法如何改变你的编程世界!
【7月更文挑战第9天】在Python的算法天地,分治、贪心、动态规划三巨头揭示了解题的智慧。分治如归并排序,将大问题拆解为小部分解决;贪心算法以局部最优求全局,如Prim的最小生成树;动态规划通过存储子问题解避免重复计算,如斐波那契数列。掌握这些,将重塑你的编程思维,点亮技术之路。
51 1
|
2月前
|
存储 算法 大数据
Python算法高手的必修课:深入理解分治法、贪心算法、动态规划,让你的代码更智能!
【7月更文挑战第9天】在Python算法学习中,分治法(如归并排序)将大问题分解为小部分递归解决;贪心算法(如货币找零)在每步选择局部最优解尝试达到全局最优;动态规划(如斐波那契数列)通过存储子问题解避免重复计算,解决重叠子问题。掌握这三种方法能提升代码效率,解决复杂问题。
35 1