目录
一、题目描述
来源:购物单_牛客题霸_牛客网
二、题目分析
该题类似于0-1背包问题,关于0-1背包请看0-1背包-动态规划算法_哔哩哔哩_bilibili
1、题目理解
1、购买附件必须买主件,且一个主件最多有两个附件,每件物品只能购买一次;
2、每件物品有三个属性:价格v、重要度p、是主件还是附件q,满意度是价格v和重要度p的数学期望,q为该附件所属主件的编号,q=0表示该物品是主件;
3、手中有N元钱,要买m件物品,使得产生的满意度最大。
2、题目分析
该题与0-1背包相比,难点在于该题有附件关联着,买附件还必须要买主件,有四种情况要讨论:
1、只买主件;
2、买主件+附件一;
3、买主件+附件二;
4、买主件+附件一+附件二;
因为一个主件最多有两个不同的附件,因此两个附件要分开讨论,那么我们遍历物品的时候,可以略过附件,只在买主件的时候考虑附件的情况。
(1)首先,将物品类准备好
包含上述所说的三个属性v、p、q,另外为了区分附件一和附件二,再加两个属性a1和a2分别代表附件一和附件二,初始化为0表示为主件,并生成相应的set方法,方便对a1和a2进行修改,生成有参构造,以便对物品初始化,toString方法是为了方便调试。
class Goods {
int v; //价格
int p; //重要度
int q; //是否为附件
int a1 = 0, a2 = 0;
public Goods(int v, int p, int q) {
this.v = v;
this.p = p;
this.q = q;
}
@Override
public String toString() {
return "Goods{" +
"v=" + v +
", p=" + p +
", q=" + q +
", a1=" + a1 +
", a2=" + a2 +
'}';
}
public void setA1(int a1) {
this.a1 = a1;
}
public void setA2(int a2) {
this.a2 = a2;
}
}
(2)然后,对v、p、q进行初始化
新建方法maxValueShop(int[][] list, int N),传入控制台输入的参数,list为代表物品的二维数组,N为预算,也就是手中拥有的钱数,首先对接收的物品信息作初始化,新建一维数组v[]、p[]、q[]接收对应的值,list[i][0]表示价格放入v[]中,list[i][1]表示重要度放入p[]中,list[i][2]表示是主件还是附件放入q[]中,类似于0-1背包,三个数组新建的时候,长度要比物品数量大1,因为有一个0作为初始值,同样物品类数组goods[]长度也要大1,用以上的三个数组来构造物品类,因为刚刚构造的物品类主件都不包含附件a1和a2,需要对a1和a2进行初始化,以上实现代码如下: