/*
说明:
给定N件物品 和一个揹包 物品i的重量是wi 价值为vi 揹包容量为C 问如何装入 使揹包里物品价值最大化
该件物品要么装 要么不装 不能分开
两种问题要求(1)只要价值最大化 不管是否装满 (2)在恰好装满的情况下 价值最大化
解答:
针对两种提问 均可以使用动态规划的问题来解决 算法完全一样 只是两种初始化不一样罢了
在第二种情况下 如果得到的结果是无穷小的值 证明不能恰好装满的
01揹包的变种:
物品可以分割 那这种就比较简单了
解答:
先对没见物品计算其没磅的价值,按照贪心策略 对具有最大没磅价值的物品多拿 如果拿完之后则继续拿次大的每磅价值的物品
01揹包变种 2
在01揹包的基础上 只需改变一个条件 就是允许物品重复装
那这个问题就转变成了一个钢条的切割问题了 怎么切割 价值最多化
同样利用动态规划可以解答
*/
int pack_01(price a[],int lena,int weight,bool is_full)
{
int* w = (int*)malloc(sizeof(int)*(lena +1));
int* v = (int*)malloc(sizeof(int)*(lena +1));
w[0] = 0;
v[0] = 0;
for(int i = 0;i<lena;i++)
{
w[i+1] = a[i].len; //第i件物品的重量
v[i+1] = a[i].value; //第i件物品的价值
}
int** c = (int**)malloc(sizeof(int*) * (lena + 1));
for(int i = 0;i<lena +1;i++)
c[i] = (int*)malloc(sizeof(int) * (weight + 1));
// init
for(int i = 0;i<lena+1;i++)
c[i][0] = 0;
for(int i=0;i<weight+1;i++)
{
if(is_full)
c[0][i] = -99999; //最小值 如果结果也是负值 则证明不能恰好装满
else
c[0][i] = 0;
}
c[0][0] = 0;
for(int i = 1;i<lena +1;i++)
for(int j =1;j<weight+ 1;j++)
{
if(j<w[i])
c[i][j] = c[i-1][j];
else
c[i][j] = max(c[i-1][j],c[i-1][j-w[i]] +v[i] );
}
int ret = c[lena][weight];
for(int i = 0;i<lena+1;i++)
free(c[i]);
free(c);
free(v);
free(w);
return ret;
}