题目描述
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过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
说明
NOIP 2006 提高组 第二题

【分析】:
基本思路
这是一个 有依赖(?) 的01背包

既然物品分为主件和附件两类,且每个主件最多包含两个附件,那么我们不妨枚举所有的主件。那么,对于每次枚举,会有五种情况:

什么都不买
只买主件
买主件和第一个附件
买主件和第二个附件
买主件和两个附件
只要把这四种情况最终的价值算出来,取最大值就可以了。

#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 32005;
const int N = 105;
#define ll long longint n, m;
int a, b, c;
int v[N],q[N],p[N], v1[N],q1[N],v2[N],q2[N],dp[maxn];int main()
{while(cin >> n >> m){for(int i=1; i<=m; i++){cin >> a >> b >> c;if(c==0){v[i]=a; q[i]=b;}else{if(q1[c]==0){v1[c]=a;q1[c]=b;}else{v2[c]=a; q2[c]=b;}}}for(int i=1; i<=m; i++){for(int j=n; j>=v[i]; j--){if(j-v[i]>=0){dp[j]=max(dp[j], dp[j-v[i]] + v[i]*q[i]);}if(j-v[i]-v1[i]>=0){dp[j]=max(dp[j], dp[j-v[i]-v1[i]] + v[i]*q[i] + v1[i]*q1[i]);}if(j-v[i]-v2[i]>=0){dp[j]=max(dp[j], dp[j-v[i]-v2[i]] + v[i]*q[i] + v2[i]*q2[i]);}if(j-v[i]-v1[i]-v2[i]>=0){dp[j]=max(dp[j], dp[j-v[i]-v1[i]-v2[i]] + v[i]*q[i] + v1[i]*q1[i] + v2[i]*q2[i]);}}}cout<<dp[n]<<endl;}
}
此题是01背包问题的变形。物品的重要度乘以价格是背包问题中的价值,物品的价格是背包问题中的体积。1、我们可以把如何在众多主件与附件之中选择购买的问题转变为看成购买的5种方案:(1)什么都不买,(2)只买主件,(3)买主件和附件1,(4)买主件和附件2,(5)买主件和两个附件。2、有些主件有附件,而有些没有,这为我们思考带来了负担,我们完全可以假设任何主件都有两个附件,也就是说如果题目没有给出某个主件的附件的话,我们就假设这个主件的附件是存在的,且价格和重要度都等于0。这个假设首先不会影响到程序的正确性,也不会增加多少运算时间,且这种假设使得我们想问题和写程序都变得简单多了。3、题目中的价格都是10的这个条件,可以减少一些时间和空间的开销。此题和01背包问题有2个主要的区别:区别一:01背包问题对当前物品考虑的只有买和不买两种情况,而此题需要考虑上面所说的5种不同的购买方案。区别二:01背包问题是用v[i]来保存第i个物品的价值,而此题需要用v[i]来保存第i个物品和它的两个附件的价值,此时我们需要二维数组来实现,物品体积w同样需要用二维数组来保存。v[i][0]表示第i个物品的主件价值, v[i][1]表示第i个物品的第一个附件的价值,v[i][2]表示第i个物品的第二个附件的价值 .w[i][0..2]表示同样的物品的体积。f[i,j]表示给定i个物品和j的空间能够获得的最大价值总合。则: f[i,j]=max{f[i-1,j],f[i-1,j-w[i,0]]+v[i,0],f[i-1,j-w[i,0]-w[i,1]]+v[i,0]+v[i,1],f[i-1,j-w[i,0]-w[i,2]]+v[i,0]+v[i,2],f[i-1,j-w[i,0]-w[i,1]-w[i,2]]+v[i,0]+v[i,1]+v[i,2]}
其实,此题还有一个关键点,就是输入数据的处理。
根据题目的意思,q是物品的编号,但是这个编号是在考虑附件时统计的编号,而我们认为附件和主件是一体的,因此附件编号因该和主件一致,所以我们需要对题目给出的编号进行转换。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>using namespace std;  const int maxn = 40000;  int f[70][maxn];  int value[70][3],imp[70][3];  int main()  {  int n,m;  int v,p,q;  scanf("%d%d",&n,&m);   for(int i=1; i<=m; i++)  {  scanf("%d%d%d",&v,&p,&q);  //为主件   if (!q)  {  value[i][0] = v;  imp[i][0] = p;  }  //为附件   else  {  if (!value[q][1])  {  value[q][1] = v;  imp[q][1] = p;  }  else  {  value[q][2] = v;  imp[q][2] = p;  }  }  }          memset(f,0,sizeof(f));   for(int i=1; i<=m; i++)  {  for(int j=1; j<=n; j++)  {  if (j-value[i][0]>=0)  {  //仅主件   f[i][j] = max(f[i-1][j],f[i-1][j-value[i][0]] + value[i][0]*imp[i][0]);  //这个时候的f[i][j]表示仅有主件的时候的情况,而下面每种加附件的情况,都是在有主件的基础下,所以  //直接和f[i][j]比较   //主件 + 附件1   if (j-value[i][0]-value[i][1]>=0)  f[i][j] = max(f[i][j],f[i-1][j-value[i][0]-value[i][1]] + value[i][0]*imp[i][0] + value[i][1]*imp[i][1]);  //主件 + 附件2   if (j-value[i][0]-value[i][2]>=0)  f[i][j] = max(f[i][j],f[i-1][j-value[i][0]-value[i][2]] + value[i][0]*imp[i][0] + value[i][2]*imp[i][2]);  //主件 + 所有附件  if (j-value[i][0]-value[i][1]-value[i][2]>=0)  f[i][j] = max(f[i][j],f[i-1][j-value[i][0]-value[i][1]-value[i][2]] + value[i][0]*imp[i][0] + value[i][1]*imp[i][1] + value[i][2]*imp[i][2]);  }  else  f[i][j] = f[i-1][j];  }  }  printf("%d\n",f[m][n]);  return 0;  }
P.S:一开始有个assembler messages的错误,纠结的半天,原来是一开始弄的f[maxn][maxn]数组太大爆炸了,

转载于:https://www.cnblogs.com/Roni-i/p/9004691.html

洛谷 P1064 金明的预算方案【有依赖的分组背包】相关推荐

  1. [动态规划] 洛谷P1064 金明的预算方案

    洛谷P1064 金明的预算方案 题意: 每件物品都有一定的满意度,而且物品分主件附件,要买附件就必须要买主件,但是买主件不一定要买附件(一个主件最多有两个附件,也可能没有喔) 设第j件物品的价格为v[ ...

  2. 不止代码:洛谷P1064 金明的预算方案+P2014选课(依赖背包)

    文章目录 题目描述 总结 解析 解法1 解法2 代码 解法3 代码 题目描述 金明的预算方案 选课 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是, ...

  3. 洛谷 P1064 金明的预算方案

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱 ...

  4. Java实现 洛谷 P1064 金明的预算方案

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元 ...

  5. 洛谷——1064金明的预算方案————有依赖的背包

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱 ...

  6. P1064 金明的预算方案

    P1064 金明的预算方案 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置 ...

  7. P1064 金明的预算方案(分组背包)

    https://www.luogu.org/problemnew/show/P1064 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈 ...

  8. AcWing 487. 金明的预算方案 (有依赖关系的背包问题)

    题意 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间. 更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就 ...

  9. luogu P1064 金明的预算方案

    传送门 这题最难了(认真 发现自己之前搞得树上背包又凉了... 写了一个O(n*V)的dfs序优化贴一下吧 50 minutes later... MD这题怎么D不出来 结果这题不是典型的树dp 因为 ...

最新文章

  1. Flutter底部导航栏BottomNavigationBar
  2. C++:const分配内存情况分析
  3. WSAStartup()函数以及DLL的加载
  4. 三连冠!百度PARL 拿下NeurIPS 2020电网调度竞赛双赛道冠军
  5. 标签的宽度_27 表格标签
  6. Freemarker中如何遍历List
  7. Linux里10个最危险的命令
  8. 哈尔滨理工C语言程序设计精髓_【注意啦】哈尔滨工业大学2020考研计算机专业课调整,难度提升!...
  9. 2021凯络趋势报告
  10. Android:Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值
  11. 第一回 钟碧诚 被迫上屋顶
  12. 审计机构不用计算机审计,计算机审计存在哪些风险
  13. python图片合成的示例
  14. 个人电子邮箱怎么注册?
  15. rxjava背压_Rx系列第十八篇:RxJava之背压策略
  16. CSGO 详细控制台指令(更新中)
  17. python中类的self到底是什么
  18. 分享数百个 HT 工业互联网 2D 3D 可视化应用案例
  19. 【maven本地打包脚本】Git/Svn代码更新+maven打包流水线
  20. Springboot 项目打包上传到私服 Nexus3,如何通过私服下载自己上传的jar包,Nexus3的搭建和使用(二)

热门文章

  1. 1.10 编程基础之简单排序 04 奖学金 7分 python
  2. 1.9 编程基础之二分查找 13:整数去重 python
  3. android /system,android:fitSystemWindows详解
  4. Qt笔记-QWebView完整加载页面及获取cookie
  5. RESTful API实现APP订餐实例
  6. 11相机不流畅_小米11有望本月发布,小米10退位让贤,256GB版本跌至3799
  7. c语言time_t转oletime,DateTimeFormatter可以格式化日期,但不能读取它自己的格式
  8. “越级”的两年后,科技潮牌realme与年轻人进行了一次深度对话
  9. python自带的解释器叫做_21条python面试题,值得收藏!
  10. otdr全部曲线图带解说_副业推荐:电影解说号,4个快速见收益的技巧