首页 > 其他分享 >动态规划

动态规划

时间:2024-04-06 23:11:57浏览次数:15  
标签:背包 int 枚举 01 物品 动态 规划 dp

背包

快熄灯了,写得有点急

01背包

给m个物品让你装进最大载重为t的背包,每个物品重量和价值,每种物品只能放一次,问最大价值

朴素做法

设dp[i][j]为只取前i个物品中并且容量为j的最佳情况
可以想到两种情况1.不选当前物体,则dp[i][j]=dp[i-1][j]
2.选当前物体则需要为当前物体腾出来wi的位置,方程为dp[i][j]=dp[i-1][j-w[i]]+v[i].

	for(int i=1;i<=m;i++)
	{
		for(int j=0;j<=t;j++)
		{
			dp[i][j]=dp[i-1][j];
		    if(j>=w[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
		}
	}
	printf("%d",dp[m][t]);
}

优化做法

由于我们每次选择时只涉及到i和i-1,我们可以将二维压缩至一维,至于怎么体现原来的i和i-1,就需要我们在内层循环反着枚举一遍容量。原理是如果我们如果正着枚举那么在我们肯定会先更新dp[j-w[i]]再更新dp[j],也就是说在更新dpj时必然会收到本次i循环前面的结果的影响,但如果反过来枚举的话就不会收到本次i循环影响,也就是说使用的dp[j-w[i]]都是在i为i-1时的结果,也就是在i-1的基础上更新。
for(int i=1;i<=m;i++)
	{
		for(int j=t;j>=w[i];j--)
		{
			dp[j]=max(dp[j-w[i]]+v[i],dp[j]);
		}
	}

完全背包

和01背包的不同是每个物品可以放多次
最朴素做法是加一层循环看放入多少个i物品

	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			for(int k=0;k*w[i]<=j;k++)
			{
				dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+v[i]*k);
			}
		}
	}

这个是二维优化版本
image
把所有k拆开我们可以得到dp方程大概是这么个结果,然后我们发现后面的一大坨就等于f[i,j-w[i]]+vi

for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			dp[i][j]=dp[i-1][j];
			if(j>=w[i]) dp[i][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
		}
	}

代码和01背包的唯一不同是dp[i][j-w[i]]中在01背包是dp[i-1][j-w[i]].
原因在于01背包只能由上一个物品转移来,而完全背包可以从当前物品转移多次而来.

优化版本

和01背包唯一不同是内层循环是正着枚举
刚才说过如果正着循环会导致当前i影响到结果,但在完全背包中我们一个i需要取多次所以正好需要结果根据当前i进行变动

for(int i=1;i<=n;i++)
	{
		for(int j=w[i];j<=m;j++)
		{
			dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
		}
	}

多重背包

每个物品不是只能取一次也不是无限次而是指定次数,并且每个物品的次数可以不同。

朴素版本

和完全背包最朴素版本基本类似,不过增加一个数量限制不能超过si

for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			for(int k=0;k<=s[i]&&k*w[i]<=j;k++)
			dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]*k]+v[i]*k);
		}
	}

优化版本

二进制优化法,因为我们种物品都有多个,我们可以将同种物品分为好多堆,采用二进制分法。假如a物品有7个那么就分为1+2+4,如果是8就是1+2+4+1,是15就是1+2+4+8,以此类推。然后我们就将n个a种物品分成了logn个,然后将所有物品都这样分一起做01背包即可。(n以内的每个数都可以被不同堆之间相加所得并且不重复)

cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		int sum=1;
		while(sum<=c)
		{
			cnt++;
			v[cnt]=sum*b;
			w[cnt]=sum*a;
			c-=sum;
			sum*=2;
		}
		if(c>0)
		{
			cnt++;
			v[cnt]=c*b;
			w[cnt]=c*a;
		}
	}
	for(int i=1;i<=cnt;i++)
	{
		for(int j=m;j>=w[i];j--)
		{
			dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
		}
	}
	cout<<dp[m];

分组背包问题

将物品分为多个组,相同组的物品只能取一次,我们采用三重循环,第二层是由大到小枚举,原因是同组物品只能取一次因此要像01背包一样,大概像是对每一组分别进行01背包的感觉。并且由于每一组内的物品质量不一定相同所以要枚举到0并且要判断当前j是否大于等于物品重量

	for(int i=1;i<=n;i++)
	{
		for(int j=m;j>=0;j--)//同组不能重复取
		{
			for(int k=1;k<=s[i];k++) 
			{
			if(j>=w[i][k]) dp[j]=max(dp[j],dp[j-w[i][k]]+v[i][k]);
			}
		 } 
	 } 

标签:背包,int,枚举,01,物品,动态,规划,dp
From: https://www.cnblogs.com/miku-dayo/p/18118148

相关文章

  • 拿捏动态内存分配!!!
    几日不见,甚是想念今天我们来拿捏动态内存分配,很重要哦1.为什么要有动态内存分配我们已经掌握的内存开辟方式有:intval=20;//在栈空间上开辟四个字节chararr[10]={0};//在栈空间上开辟10个字节的连续空间但是上述的开辟空间的方式有两个特点:•空间开辟大小是......
  • [蓝桥杯 2022 省 B] 李白打酒加强版(三维动态规划)
        通过题目描述,我们可以知道这道题目涉及到某种状态时候的方案数,因此我们可以用动态规划来解决问题,并且我们需要注意到酒的状态,因此我们可以用三维数组来存储状态,我们知道N,M最大不会超过100,并且如果酒超过了100斗,即使遇到100朵花也无法喝完,因此只需要定义大小都为1......
  • P2542 [AHOI2005] 航线规划
    P2542[AHOI2005]航线规划trick+树剖首先删边操作困难,考虑倒序处理。发现题目中的关键性质:无论航线如何被破坏,任意时刻任意两个星球都能够相互到达。在整个数据中,任意两个星球之间最多只可能存在一条直接的航线。这说明无论何时图都是连通的,那么我们完全可以建一棵树,再考虑加......
  • 【MATLAB源码-第171期】基于matlab的布谷鸟优化算法(COA)无人机三维路径规划,输出做短路
    操作环境:MATLAB2022a1、算法描述布谷鸟优化算法(CuckooOptimizationAlgorithm,COA)是一种启发式搜索算法,其设计灵感源自于布谷鸟的独特生活习性,尤其是它们的寄生繁殖行为。该算法通过模拟布谷鸟在自然界中的行为特点,为解决各种复杂的优化问题提供了一种新颖的方法。从算法......
  • 【Java】jdk1.8 Java代理模式,Jdk动态代理讲解(非常详细,附带class文件)
      ......
  • 大型集团企业IT信息化、IT应用蓝图及BI应用蓝图规划规划建设方案146页PPT格式
    原文《大型集团企业IT信息化、IT应用蓝图及BI应用蓝图规划规划建设方案》PPT格式,共146页。来源网络,旨在交流学习,如有侵权,联系速删,更多参考公众号:优享智库一、IT应用蓝图规划IT应用蓝图总图、人力资源管理、竞争情报管理、审计管理、战略管理、投资管理、财务管理、计划预......
  • 从无到有开始创建动态顺序表——C语言实现
    顺序表的概念    顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。在物理结构和逻辑结构都是连续的,物理结构是指顺序表在计算机内存的存储方式,逻辑结构是我们思考的形式,顺序表和数组是类似的,都是使用了连续的空间进行数据的保存,由于是连续的空间,所......
  • 举例:配置动态LACP模式Eth-Trunk
    举例:配置动态LACP模式Eth-Trunk组网需求如图3-13所示,服务器A与DeviceA建立动态LACP模式链路聚合,两端设备将通过动态LACP协议报文进行链路聚合协商。图3-13 动态LACP模式Eth-Trunk组网图本例中interface1、interface2、interface3分别代表10GE1/0/1、10GE1/0/2、10GE1/0/......
  • 水果云仓_统一商品标准_统一销售_统一供货_统一分拣_统一配送_按品结算_财务清分_生鲜
    水果云仓_统一商品标准_统一销售_统一供货_统一分拣_统一配送_按品结算_财务清分_生鲜配送供应链系统_杭州生鲜配送系统之升鲜宝_大批量分拣_轨道动态秤使用(一)生鲜配送现在目前应用比较多的,就是按商品分拣,选择商品、电子秤传输数量、打印标签,然后按标签将商品放至对应的区域,所谓......
  • 接龙序列(动态规划c++实现)
    题目对于一个长度为K的整数数列:A1,A2,…,AK,我们称之为接龙数列当且仅当Ai的首位数字恰好等于Ai−1的末位数字(2≤i≤K)。例如12,23,35,56,61,11是接龙数列;12,23,34,56不是接龙数列,因为56的首位数字不等于34的末位数字。所有长度为1的整数数列都是接龙数列......