2020-09-07

0-1背包问题

m(i,j) =     i == 1,j>=w[1]?v[1]:0

                i>1&&i<=n

                                j<w[i],m(i-1,j)

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

//        物品数量,背包容量,物品各重量,物品各价值,动态规划组
void Knapsack(int n,int bagv,int w[],int v[],int **f)//最终的f[i][j]就是最大价值
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=bagv;j++)
		{
			if(j < w[i])
				f[i][j] = f[i-1][j];
			else
				f[i][j] = max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
		}
	}
}
//标记最大价值的组成路径
void findWhat(int i,int j,int item[],int w[],int v[],int **f)
{
	if(i >= 0)
	{
		if(f[i][j] == f[i-1][j])
		{
			item[i] = 0;
			findWhat(i-1,j,item,w,v,f);
		}
		else if(j-w[i] >= 0 && f[i][j] == f[i-1][j-w[i]]+v[i])
		{
			item[i] = 1;
			findWhat(i-1,j-w[i],item,w,v,f);
		}
	}
}

多重背包:

 输入的第 1 行,为两个正整数,用一个空格隔开:N m
(其中 N ( <32000 )表示总钱数, m ( <60 )为希望购买物品的个数。)
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q
(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 ~ 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)
思路:

1、主辅件之分(依题:主件存在0列,附件存在1、2列),最终的比较值也就是背包中的价值

2、pre[][]各件的价钱与重要度的乘积,cro[][]各件的价钱,tot[]最大值的存储域

for(int i=1;i<=m;i++)
	{
		for(int j=n;j>=cro[i][0];j--)
		{
			if(j >= cro[i][0])
			{
				tot[j] = max(tot[j-cro[i][0]]+pre[i][0],tot[j]);
			}
			int vt = cro[i][0]+cro[i][1];
			if(cro[i][1] != 0)
			{
				if(j >= vt)
					tot[j] = max(tot[j-vt]+pre[i][0]+pre[i][1],tot[j]);
			}
			vt = cro[i][0]+cro[i][1]+cro[i][2];
			if(cro[i][2] != 0)
			{
				if(j >= vt)
					tot[j] = max(tot[j-vt]+pre[i][0]+pre[i][1]+pre[i][2],tot[j]);
			}
		}
	}

有关0-1背包其他解决办法,及完全背包、多重背包问题可参考:

https://blog.csdn.net/weixin_43249938/article/details/88217034
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值