Time Limit: 1 second

Memory Limit: 50 MB

【问题描述】

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:

主件 附件
电脑 打印机、扫描仪
书柜 图书
书桌 台灯、文具
工作椅

如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是10元的整数倍)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

    设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1,j2,……,jk,则所求的总和为:

    v[j1]*w[j1]+v[j2]*w[j2]+
…+v[jk]*w[jk]。(其中*为乘号)

    请你帮助金明设计一个满足要求的购物单。

【输入】

的第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

【输出样例1】

    2200

【题解】

注意每个主件最多只有两个附件

把有依赖关系的物品包裹在一起。

然后包裹中的物品是(x是主件)

x,x+y,x+z,x+y+z;

相互冲突。只取一个。

分组背包

物品的重量是每个物品的钱数,价值是钱数*重要度。

【代码】

#include <cstdio>

int n, m, bianhao = 0, new_bianhao[70], a[70][70] = { 0 }, w[70], c[70], f[32001];

void input_data()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
int v, p, q;
scanf("%d%d%d", &v, &p, &q); //输入它的价格 重要度 和类型
w[i] = v;
c[i] = v*p; //价值为价格乘重要度
if (q == 0) //如果是主件则增加组数。
{
bianhao++;
new_bianhao[i] = bianhao; //记录这个物品是哪个组
a[bianhao][0]++; //用a数组来记录组中的物品信息。
a[bianhao][a[bianhao][0]] = i;
}
else
a[new_bianhao[q]][++a[new_bianhao[q]][0]] = i; //如果是附属某个主件则
//获取这个主件所在的组。同时把这个物品加入到该组中。
}
} void get_ans()
{
for (int k = 1;k <= bianhao;k++) //枚举bianhao个组
for (int j = n; j >= 0; j--) //逆序枚举最大值。表示这是0/1背包类
{ //少了枚举每个组中的各个物品哪个循环。而直接列出所有的可能情况。
//根据x,x+y,x+y+z,x+z这几种情况尝试更新f[j];
if (j >= w[a[k][1]] && f[j - w[a[k][1]]] + c[a[k][1]] > f[j])
f[j] = f[j - w[a[k][1]]] + c[a[k][1]];
if (j >= w[a[k][1]] + w[a[k][2]] && f[j - w[a[k][1]] - w[a[k][2]]] + c[a[k][1]] + c[a[k][2]] > f[j])
f[j] = f[j - w[a[k][1]] - w[a[k][2]]] + c[a[k][1]] + c[a[k][2]];
if (j >= w[a[k][1]] + w[a[k][2]] + w[a[k][3]] && f[j - w[a[k][1]] - w[a[k][2]]-w[a[k][3]]] + c[a[k][1]] + c[a[k][2]]+c[a[k][3]] > f[j])
f[j] = f[j - w[a[k][1]] - w[a[k][2]]-w[a[k][3]]] + c[a[k][1]] + c[a[k][2]]+c[a[k][3]];
if (j >= w[a[k][1]] + w[a[k][3]] && f[j - w[a[k][1]] - w[a[k][3]]] + c[a[k][1]] + c[a[k][3]] > f[j])
f[j] = f[j - w[a[k][1]] - w[a[k][3]]] + c[a[k][1]] + c[a[k][3]];
}
} void output_ans()
{
printf("%d\n", f[n]);
} int main()
{
input_data();
get_ans();
output_ans();
return 0;
}

最新文章

  1. Python之路,Day6 - Python基础6
  2. 移动端webUI框架(HTML5手机框架)
  3. Spark RDD 多文件输入
  4. Swift语言之命令模式(Command Pattern)实现
  5. JQuery按回车提交数据
  6. HDU2509 Be the Winner
  7. div+css文字垂直居中 解决左侧头像右侧姓名,姓名多换行后相对于头像仍居中显示
  8. oc-数据模型的建立
  9. acdream1116 Gao the string!(hash二分 or 后缀数组)
  10. SuperToolTips
  11. hdu 2642 二维树状数组 单点更新区间查询 模板水题
  12. ubuntu linux 13.04更新
  13. mvcSSHweb.xml要配置的信息
  14. TSL 访问器
  15. 批量修改所有服务器的dbmail配置
  16. java 安装环境
  17. 24.ArrayBuffer
  18. webpack 项目实践
  19. Android开发日记(一)
  20. ansible批量验证密码

热门文章

  1. HTML5手机应用的最大优势就是可以在网页上直接调试和修改
  2. BZOJ1396: 识别子串(后缀自动机,线段树)
  3. 阅读笔记——Servlet
  4. 【2017 Multi-University Training Contest - Team 6】Kirinriki
  5. 决策树2 -- CART算法
  6. ORA-01078错误举例:SID的大写和小写错误
  7. 怎样 TabHostFragment自己定义 tab键(indicator)
  8. VMware Ubuntu安装详细过程(详细图解)
  9. 【Codeforces Round #431 (Div. 1) B】
  10. Java中关于static语句块的理解