![NC16671 [NOIP2006]金明的预算方案](https://img2022.cnblogs.com/blog/2521724/202209/2521724-20220913134807804-1217068601.png)
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过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]。(其中*为乘号)
请你帮助金明设计一个满足要求的购物单。
题目
- 原题地址:[NOIP2006]金明的预算方案
- 题目编号:NC16671
- 题目类型:DP、分组背包
- 时间限制:C/C++ 1秒,其他语言2秒
- 空间限制:C/C++ 32768K,其他语言65536K
1.题目大意
- 总钱数为
n,有m个物品,每个物品有价格v,重要度p,从属关系q,求不超过总钱数,可以得到的重要度与价格乘积的最大值。
![]()
2.题目分析
v存价格,p存重要度与价格的乘积,q存从属关系,f[i]存使用钱数不超过i时的可获得的最大乘积值,g[i]存中间计算量
- 每次选择主物品,初始化数组
g,更新g为容量为k时不选择从物品和容量为k-v[j]时选择选择从物品的乘积最大值
- 最后用
g来更新f,取每个元素的较大者为新的f
3.题目代码
#include <bits/stdc++.h>
using namespace std;
int n, m, v[66], p[66], q[66], g[32003], f[32003];
int main() {
cin >> n >> m;
for(int i=1;i<=m;i++) cin >> v[i] >> p[i] >> q[i], p[i] *= v[i];
for(int i=1;i<=m;i++) {if(!q[i]) {
for(int j=v[i];j<=n;j++) g[j] = f[j-v[i]] + p[i];
for(int j=1;j<=m;j++) if(q[j]==i)
for(int k=n;k>=v[i]+v[j];k--)
g[k] = max(g[k], g[k-v[j]]+p[j]);
} for(int j=1;j<=n;j++) f[j] = max(f[j], g[j]);
} cout << f[n] << endl;
}