金明的预算

【问题描述】

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

【输入样例】

1000 5

800 2 0

400 5 1

300 5 1

400 3 0

500 2 0

【输出样例】

2200

思路

这个题虽然没有讲先主件还是附件,样例是先主件,但是也有附件先输入的情况,我看了下数据并没有,所以无需管它。这个其实就是一个「分组背包」问题,以「主件」开始

1、        可以选「附件」可以不选「附件」

2、        (附件最多两种)可以选一个「附件」也可以选另外一个「附件」

3、        可以两个「附件」都选

以上三条一共就是四种情况(一个「主件」和两个「附件」看作1,2,3):1,1和2,1和3,1和2和3   四种情况

然后讲讲存储

F[i][j][k] 开的范围是f[70][5][3]

i代表第i行

j代表第i行四种情况(1,12,13,123上述所讲)

k有着1和2的两个位置,1代表f[i][j]的价值,2代表f[i][j]的代价(重量)

然后每次读入就用一个num[i]数组来存储第i行有多少个数字

void input()
{
for (int i=1;i<=n;i++){scanf("%d%d%d",&v[i],&p[i],&q[i]);//v[i]代表代价  p[i]重要度  q[i]主件为0/附件地址 if (!q[i]) //如果是主件{num[i]++;f[i][1][1]=v[i]*p[i];//价值 放第一个f[i][1][2]=v[i];//代价  放第一个}else{num[q[i]]++;//num[i]是存储第i行有多少数 f[q[i]][num[q[i]]][1]=v[i]*p[i];//价值 f[q[i]][num[q[i]]][2]=v[i];//代价 }}
}

然后就是解决四种(1,12,13,123)情况了 我比较笨,就手打了,预处理一下

void pretreatment()
{
for (int i=1;i<=n;i++){if (num[i]==3) num[i]++;f[i][2][1]+=f[i][1][1];f[i][2][2]+=f[i][1][2];f[i][3][1]+=f[i][1][1];f[i][3][2]+=f[i][1][2];f[i][4][1]=f[i][2][1]+f[i][3][1]-f[i][1][1];f[i][4][2]=f[i][2][2]+f[i][3][2]-f[i][1][2];}//这里把(1,12,13,123处理了具体自己看不难理解)
}

接下来就到了work处理背包的地方了

这就是个分组背包 在每i行只能选一个

背包的模板

void work()
{for (int i=1;i<=n;i++)//第i行if (num[i]>0)//如果这一行有数字也就是有主件,因为我把附件贴到了应该 的主件上并且没有num[i]++所以附件该行为0for (int j=m;j>=0;j--)//容量逆着推for (int k=1;k<=num[i];k++)//模拟最多四种情况{if(f[i][k][2]<=j)//支付的起s[j]=max(s[j],s[j-f[i][k][2]]+f[i][k][1]);//dp转移方程}
}

--------------------------------------------------------------------------------------------------------------Finished-------------------------------------------------------------------------------------------------------------
源代码奉上

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int m,n,v[70],p[70],q[70],x=0,f[70][5][3],num[70]={0},s[32000];//f[i][j][1]存储价值,f[i][j][2]存储代价
void input()
{for (int i=1;i<=n;i++){scanf("%d%d%d",&v[i],&p[i],&q[i]);//v[i]代表代价  p[i]重要度  q[i]主件为0/附件地址 if (!q[i]) {num[i]++;f[i][1][1]=v[i]*p[i];//价值 f[i][1][2]=v[i];//代价 }else{num[q[i]]++;//num[i]是存储第i行有多少数 f[q[i]][num[q[i]]][1]=v[i]*p[i];//价值 f[q[i]][num[q[i]]][2]=v[i];//代价 }}
}
void pretreatment()
{for (int i=1;i<=n;i++){if (num[i]==3) num[i]++;f[i][2][1]+=f[i][1][1];f[i][2][2]+=f[i][1][2];f[i][3][1]+=f[i][1][1];f[i][3][2]+=f[i][1][2];f[i][4][1]=f[i][2][1]+f[i][3][1]-f[i][1][1];f[i][4][2]=f[i][2][2]+f[i][3][2]-f[i][1][2];}
}
void work()
{for (int i=1;i<=n;i++)if (num[i]>0)for (int j=m;j>=0;j--)for (int k=1;k<=num[i];k++){if(f[i][k][2]<=j)s[j]=max(s[j],s[j-f[i][k][2]]+f[i][k][1]);}
}
int main()
{memset(f,0x7f,sizeof(f));scanf("%d%d",&m,&n);input();pretreatment();work();cout<<s[m];
}

具体见上方思路
PS: 在过程中可以打一个examine检查的过程看看是不是自己想要的情况

void examine()
{ cout<<"thing:"<<endl;for (int i=1;i<=n;i++){for (int j=1;j<=num[i];j++)cout<<thing[i][j][1]<<" ";cout<<endl;}cout<<"cost:"<<endl;for (int i=1;i<=n;i++){for (int j=1;j<=num[i];j++)cout<<thing[i][j][2]<<" ";cout<<endl;}
}

大功告成

金明的预算budget题解相关推荐

  1. 金明的预算方案-题解

    稍微难一点的01背包问题. 可以用w[i][0]来存主件,w[i][1],w[i][2]来存附件 本题的状态转移方程就显而易见了: d p [ j ] = m a x { d p [ j − w [ ...

  2. P1064 [NOIP2006 提高组] 金明的预算方案

    P1064 [NOIP2006 提高组] 金明的预算方案 题意: 每个物品有价格和价值,物品之间存在依赖关系(单向的),现在又n元钱,买哪些物品,即满足依赖关系又使得每件物品的价格与价值的乘积的总和最 ...

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

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

  4. 背包形动态规划 fjutoj2375 金明的预算方案

    金明的预算方案 TimeLimit:1000MS  MemoryLimit:128MB 64-bit integer IO format:%lld Problem Description 金明今天很开 ...

  5. 信息学奥赛一本通 1844:【06NOIP提高组】金明的预算方案 | 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案

    [题目链接] ybt 1844:[06NOIP提高组]金明的预算方案 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案 [题目考点] 1. 动态规划:分组背包 2. 动态规划:依赖背包 ...

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

    T2 金明的预算方案 http://www.tyvj.cn/p/1057 背景 NOIP2006 提高组 第二道 描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房 ...

  7. 算法提高 金明的预算方案

    算法提高 金明的预算方案   时间限制:1.0s   内存限制:256.0MB      问题描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是, ...

  8. 【背包DP练习】洛谷 P5020货币系统 P1757通天之分组背包 P1064[NOIP2006 提高组]金明的预算方案 P5322 [BJOI2019]排兵布阵

    洛谷 P5020货币系统 https://www.luogu.com.cn/problem/P5020 思路是把货币从小到大排序,然后按顺序依次完全背包dp,每次dp检查i-1种面值的货币能不能凑出第 ...

  9. 【每日DP】day7P1064 金明的预算方案 (分组背包,我又悟了)难度⭐⭐★

    P1064 金明的预算方案 背包其实就是把一个大问题拆分成若干个子问题,把一个要拿东西的动作按照题目要求分成若干个动作,分别枚举(DP其实就是非常的暴力),比较取最大值. 比如这道题,背包的物品之间是 ...

最新文章

  1. java 函数式编程_函数式编程杂谈
  2. 详解网络摄像机中的IR-CUT
  3. 启明云端分享| ESP32-S3 + 480*480分辨率的2.1寸圆屏旋钮方案
  4. c语言字符型计算器,求用c语言编程四则混合运算计算器?
  5. 计算机一级excel如何选择2个,2017年计算机一级excel操作题(2)
  6. ROS服务中自定义数据类型
  7. TextBoxWatermarkExtender扩展器与RequiredFieldValidator控件相冲突的解决方案
  8. VMware 披露严重0day,影响Workspace One 的多个组件
  9. 个人简历怎么写怎么做(还有怎么培养无私奉献的精神--模板)
  10. vs 2015 密钥
  11. 洛谷-明明的随机数(C语言实现)
  12. seaborn关联图表之折线图和散点图
  13. 使用<details>标签在网页里面添加脚注
  14. python好学吗一般要学多久-Python好学吗?精通Python需要多长时间?
  15. 【Java获取国家法定节假日三种工具类其二】
  16. win10所有文件夹都是只读
  17. S3C2440系统中断(转)
  18. java 手机 连接电脑,非智能手机怎么连接电脑
  19. oracle 索引基本原理
  20. Javascript 控制文本框的输入法切换

热门文章

  1. 界面追踪法求解流体流动的表面张力
  2. 华为桌面云虚拟机白屏无法启动的修复方法
  3. java swing 毛玻璃_实时、动态的毛玻璃(aero)效果,javaSwing 实现的,用的是高斯模糊算法...
  4. 双卡版本不插卡的情况下状态栏中只显示了一个信号图标,而不是两个信号图标,如何修改为2个图标
  5. ARM服务器安装CentOS7.4
  6. 如何在Win10系统下的IntelliJ IDEA 2018.3.5下载与安装以及激活教程
  7. php面试-职业规划
  8. Moloch安装与使用
  9. html图片切换动画,js实现图片切换(动画版)
  10. 【我可能学的是假英语】英语、中式英语、偏误英语1