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