DP背包(一)

时间:2022-07-28
本文章向大家介绍DP背包(一),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

01背包

for(int i=0;i<n;i++) //遍历每一件物品
	for(int j=v;j>=wei[i];j--)//遍历背包容量,表示在上一层的基础上,容量为J时,第i件物品装或不装的最优解;
		dp[j]=max(dp[j-wei[i]]+val[i],dp[j]);

初始化细节:装满dp[0]=0;其余赋值-INF;不装满全初始化为0;

完全背包

for(int i=0;i<n;i++) //遍历每一类物品
	for(int j=wei[i];j<=v;j++)//遍历容量,此时代表第一类物品选了几件。与0/1区别正序遍历
		dp[j]=max(dp[j-wei[i]]+val[i],dp[j]);

多重背包

for(int i=0;i<n;i++)  //遍历每一个物品 
		   for(int j=0;j<=num[i];j++)  //遍历物品的数量 
		      for(int k=m;k>=weight[i];k--)   //当做01背包来处理 
		      {  //取01背包情况的dp[k]和dp[k-weight[i]]+value[i]的最大值 
				dp[k]=max( dp[k],dp[k-weight[i]]+value[i] );
			  }

二进制优化 优化原因:

多重背包转换成 01 背包问题就是多了个初始化,把它的件数C 用 分解成若干个件数的集合,这里面数字可以组合成任意小于等于C 的件数,而且不会重复,之所以叫二进制分解,是因为这样分解可 以用数字的二进制形式来解释 比如:7的二进制 7 = 111 它可以分解成 001 010 100 这三个数可以 组合成任意小于等于7 的数,而且每种组合都会得到不同的数 15 = 1111 可分解成 0001 0010 0100 1000 四个数字 如果13 = 1101 则分解为 0001 0010 0100 0110 前三个数字可以组合成 7以内任意一个数,加上 0110 = 6 可以组合成任意一个大于6 小于13 的数,虽然有重复但总是能把 13 以内所有的数都考虑到了,基于这种 思想去把多件物品转换为,多种一件物品,就可用01 背包求解了。

for(int i=0;i<n;i++)
{
	cin>>w[i]>>v[i]>>c[i];//对每一种类的c[i]件物品进行二进制分解
	for(int j=1;j<=c[i];j<<=1){      //右移=*2 
		value[cnt]=j*v[i];
		weight[cnt]=j*w[i];
		cnt++;
		c[i]-=j; 
	} 
	if(c[i]>0){
		alue[cnt]=c[i]*v[i];
		weight[cnt]=c[i]*w[i];
		cnt++;
	}
}
01背包求解.....

好像单调队列也能优化,多重背包; 下一期整理