题目:有n种礼品,每个礼品对应一个热度值,总金额为k,每个礼品只能买一次,如何购买可以使得所有礼品的总热度值最高。
题目类型:01背包问题
方法:动态规划法
思路:动态规划的难点就是寻找递推关系式,我们现在来判断
1.包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j)
2.还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
ps:Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积,定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值,V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i),但价值增加了v(i);
所以说递推关系式如下:
j<w(i) V(i,j)=V(i-1,j)
j>=w(i) V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
思路:创建两个数组长度比原来大一的,然后将数组中的数放入,创建一个二维数组表示在第i件,还剩j时的值,两个for循环叠加递推表达式进行求解
代码:
public static int bigSum(int[] array1,int[] array2,int num){
int length = array1.length;
int[] a= new int[length+1];
int[] b= new int[length+1];
a[0]=0;
for (int i = 1; i <a.length ; i++) {
a[i]=array1[i-1];
}
b[0]=0;
for (int i = 1; i <b.length ; i++) {
b[i]=array2[i-1];
}
int[][] c= new int[length+1][num+1];
for (int i = 1; i <length+1 ; i++) {
for (int j = 1; j <num+1 ; j++) {
if(a[i]>j){
c[i][j]=c[i-1][j];
}else{
int value1=c[i-1][j-a[i]]+b[i];//拿了第i件
int value2=c[i-1][j];//没拿第i件
c[i][j]=Math.max(value1,value2);
}
}
}
return c[length][num];
}