01背包

01背包问题:

一共有n个物品(每个物品只有一个),每个物品的体积为Vi,重量为Wi。在背包容量vol一定的条件下,装入物品,使得背包总重量最大。

分析:由于物品只有一个且放入无序,所以可以人为地将物品分阶段处理,即第一阶段只考虑第一件物品并假设背包容量从0-vol进行DP,第二个阶段只考虑前两件物品并假设背包容量从0-vol进行DP,以此类推,这样的话,可以保证每个阶段都得到最优解,且上一个阶段影响下一阶段的最优解,概括得出状态转移方程:d[i][j]=max(d[i-1][j],d[i-1][j-vi])

代码:

#include<cstdio>
#include<cstring>
int dp[9680],str[100][100];
int max(int a, int b)
{
	return a > b ? a : b;
}
int main()
{
	int i, j, n,vol,v,w;
	while (scanf("%d%d",&vol,&n) != EOF)
	{
		memset(str, 0, sizeof str);
		for (i = 1;i <= n;i++)
		{
			scanf("%d%d", &v, &w);
			for (j = vol;j >= 0;j--)
				if(j>=v)
                                        str[i][j] = max(str[i - 1][j], str[i - 1][j - v] + w);
		}
		printf("%d\n", str[i-1][vol]);
	}
	return 0;
}


滚动数组:

其实,如果题目要求的输出非常简单,则可以不必存储除了最后一个阶段以外阶段的数据,并用滚动数组进行计算

分析:用以上方法计算时,状态转移的其中一种情况就是完全复制上一阶段的结果,所以我们假定当前阶段就满足这种状态转移,先将上一阶段的结果完全复制,再在当前阶段中判断是否真的满足这种情况,因此,我们可以只用一维数组来进行DP,节省了很多空间。其中从后往前进行DP的原因在于前面的结果可以影响后面的结果,但是后面的结果不能影响前面的结果,所以我们需要先计算后面的结果,而不用滚动数组时则不需考虑这个问题,从前往后或者从后往前都是一样的。同时,由于已经默认下一阶段复制到当前阶段,所以每个阶段仅需DP到假设的总空间大于或等于第i个物品的空间即可。

代码(直接把二维数组改为一维数组即可):

<pre name="code" class="cpp">#include<cstring>
int dp[9680],str[100];
int max(int a, int b)
{
	return a > b ? a : b;
}
int main()
{
	int i, j, n,vol,v,w;
	while (scanf("%d%d",&vol,&n) != EOF)
	{
		memset(str, 0, sizeof str);
		for (i = 1;i <= n;i++)
		{
			scanf("%d%d", &v, &w);
			for (j = vol;j >= v;j--)
                                str[j] = max(str[j], str[j - v] + w);
		}
		printf("%d\n", str[vol]);
	}
	return 0;
}


 

 
 


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值