概述
欢迎大家验证、留言、讨论!
链接:
问题链接
题目描述
王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅 无
如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。王强想买的东西很多,为了不超出预算,他把每件物品规定了一个重要度,分为 5 等:用整数 1 ~ 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 元的整数倍)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j 1 , j 2 ,……, j k ,则所求的总和为:
v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 为乘号)
请你帮助王强设计一个满足要求的购物单。
输入描述:
输入的第 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 是所属主件的编号)
输出描述:
输出文件只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值( <200000 )。
示例1
输入
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出
2200
——————————————————————————————————————
问题描述没有说不能购买同一个物品,而且从别人写的通过的代码来看,它是可以多次选择同一个物品购买的,如下面的例子。
写了好久,改了好久,没有人觉得这道题有问题嘛!
———————————————————————————————
输入:
30 4
10 5 4
10 5 4
10 5 0
10 1 0
拿别人通过的代码测试,答案是110!!!!!不应该是150么! 3105=150 ,不对?
110=10* 5* 2+10* 1
150=10* 5* 3
————————————————————————————————
输入:
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
给的答案是2200,不应该是2400么???
2200=500* 2+400* 3 (花了900块)
2400=2* 400 *3 (花了800块)
————————————————————————————————
后面附上自己的理解、解题过程和c++代码!
解题思路:先不要理附件的问题。
最后一步:选择了物品j,在小于等于i元的情况下,得到的权值f[i]最大。
子问题:在小于i-val[j]元的情况下,使得到的权值f[i-val[j]]最大。
目标:在小于等于i元的情况下,得到的权值f[i]最大。
可以进一步写出数学公式:
f
(
i
)
=
m
a
x
(
f
(
i
−
v
a
l
j
)
+
w
j
)
f(i)=max{(f(i-val_j)+w_j)}
f(i)=max(f(i−valj)+wj)
w
j
=
v
a
l
j
∗
p
j
w_j=val_j*p_j
wj=valj∗pj
i
是
奖
金
数
、
f
(
i
)
是
权
值
就
是
价
格
∗
重
要
度
的
总
和
,
v
j
是
物
品
j
的
价
格
,
i是奖金数、f(i)是权值就是价格*重要度的总和,v_j是物品j的价格,
i是奖金数、f(i)是权值就是价格∗重要度的总和,vj是物品j的价格,
w
j
是
物
品
j
的
权
值
、
p
j
是
物
品
j
的
重
要
度
w_j是物品j的权值、p_j是物品j的重要度
wj是物品j的权值、pj是物品j的重要度
我将输入的数据划分保存,val数组的保存主、附件的价格;w数组保存对应的重要度。
考虑附件可以选择的情况,总共有四种(因为最多两个附件):
1、只选择主件 (i要大于主件对应的价格)
2、主+附件1
3、主+附件2 (i要大于主件对应的价格+附件2的价格)
4、主+附件1+附件2
因为必须先选择主件才能选择附件,所以选择时,金钱数应大于对应项。
#include<iostream>
using namespace std;
int main()
{
int N,m,cost,sum;
cin>>N>>m;
N/=10;
int val[m][3]={0},w[m][3]={0};//初始化为0
int v,p,q;
int f[N+1]={0};
for(int i=0;i<m;i++)
{
cin>>v>>p>>q;
v/=10;
if(q==0) val[i][0]=v, w[i][0]=v*p;//val的第1列存主件的价格,w存重要程度*价格
else
{
if(val[q-1][1]==0) val[q-1][1]=v, w[q-1][1]=v*p;//val的第2列存附件1的价格
else val[q-1][2]=v, w[q-1][2]=v*p;//val的第2列存附件2的价格
}
}
for(int i=0;i<=N;i++)
{
for(int j=0;j<m;j++)
{
if(i>=val[j][0]) f[i]=max(f[i-val[j][0]]+w[j][0],f[i]);
if(i>=(val[j][0]+val[j][1])) f[i]=max(f[i-val[j][0]-val[j][1]]+w[j][0]+w[j][1],f[i]);
if(i>=(val[j][0]+val[j][2])) f[i]=max(f[i-val[j][0]-val[j][2]]+w[j][0]+w[j][2],f[i]);
if(i>=(val[j][0]+val[j][1]+val[j][2])) f[i]=
max(f[i-val[j][0]-val[j][1]-val[j][2]]+w[j][0]+w[j][1]+w[j][2],f[i]);
}
}
cout<<f[N]*10;
}
最后
以上就是干净身影为你收集整理的华为机试题-购物单的全部内容,希望文章能够帮你解决华为机试题-购物单所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复