题目样例
有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
物品个数——n
背包体积——bagV
编号为i的物品价值——v[i]
编号为i的物品体积——w[i]
思路
题目中无非涉及到两种数据——体积与价值 和对应的背包序号i
最终要是价值最大化,根据DP设置的原则我们自然想到要以价值来作为状态
用体积和序号作为状态的描述元素
这里,我简单的介绍一下一个初学者对于状态的理解
我们可以类比数学中的函数进行分析
众所周知,对于一个函数y=f(x)中每一个变量x,函数y=f(x)都有唯一而确定的值与之对应,dp的状态描述亦是如此,对于dp(a,b,c,d~),函数的参量a,b,c,d~中的任意一个参量发生改变都会使函数描述的值发生对应的变化,即对于同一参量a,b,c,d~,函数有且仅有一个值与之对应。简言之,dp()——f() a,b,c,d——x,我们可以把它类比做函数进行分析
综上所述, 我们用dp(i,w)来描述当背包有w体积时对于前i个物品能够获得的最大价值
我们知道对于数据i(背包序号)是从1开始逐个递增到m的
思考:数据w(体积)应该遵循什么样的递增方式???
这里我们应当思考对于前i个背包,其价值不会只是单一的递增,是无规律的,但是能够确定的是——在能够装下物品的情况下,我们应当采用贪心的策略,选择价值较大的物品,以此作为状态转移的原则
因此,w也是逐个递增的
那么,具体到状态转移方程上应该如何操作呢?
我们分析迭代循环的过程,当更新到dp(i,w)时,我们首先要判断w个体积能不能装下第i个物品的体积w[i]
1.倘若不能,显然这是需要纵向比较,取w个体积已知的最优解dp(i-1,w)
2.倘若可以,需要先横向操作找到装这个物品之前背包剩余空间时对应的价值dp(i-1,w-w[i]),再加上装上之后的价值v[i],得到一个解[dp(i-1,w-w[i])+v[i]],接着纵向比较,比较w个体积的已知最优解dp(i-1,w)与 该解,取其中较大的那一个。
状态转移方程
初步总结
根据上述原理,我们确定了背包问题动态规划的状态
确定了状态转移的方程
01背包问题就解决了大的框架问题
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define MAXN 1000010
using namespace std;
int n,bagV;
int v[MAXN];
int w[MAXN];
int dp[10000][10000];
int main()
{
memset(dp,0,sizeof(dp));
cin>>n>>bagV;
for(int i=1;i<=n;i++)
{
cin>>v[i];
cin>>w[i];
}
int ans=-1;
for(int i=1;i<=n;i++){//DP核心过程
for(int j=1;j<=bagV;j++){
if(j>=v[i]){
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
}
else{
dp[i][j]=dp[i-1][j];
}
ans=max(ans,dp[i][j]);
}
}
for(int i=0;i<=n;i++){//dp数组打印,方便理解
for(int j=0;j<=bagV;j++){
cout<<dp[i][j]<<" ";
}
cout<<endl;
}
cout<<ans;
return 0;
}
一些话
动态规划的基本思路已经呈现
核心就是确定状态和状态转移方程
标签:状态,背包,浅谈,int,体积,DP,物品,dp 来源: https://blog.csdn.net/LuckZY_/article/details/120809011
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。