P1064 金明的预算方案

题目描述

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

主件 附件

电脑 打印机,扫描仪

书柜 图书

书桌 台灯,文具

工作椅 无

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

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

v[j1]×w[j1]+v[j2]×w[j2]+…+v[j**kw[j**k]。

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

输入格式

第1行,为两个正整数,用一个空格隔开:

N m (其中N(<32000)表示总钱数,m(<60)为希望购买物品的个数。) 从第2行到第m+1行,第 j *行给出了编号为j-1的物品的基本数据,每行有3个非负整数

v p q (其中vv表示该物品的价格(v<10000),p表示该物品的重要度(1-5),q表示该物品是主件还是附件。如果q=0,表示该物品为主件,如果q>0,表示该物品为附件,q是所属主件的编号)

输出格式

一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<200000)。

输入输出样例

输入 #1

1
2
3
4
5
6
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

输出 #1

1
2200

1、 对于一棵子树,给予空间 v , 选择树根的情况下,对子子树们跑 01 背包。

2、先求 dfs 序列,对于一个节点 x ,

  • 如果选择 x ,那么他的子节点可以选择,d[i] 从 d[i-1] 直接转移而来
  • 如果不选择 x,那么子节点不可选,只能从左兄弟转移而来,跑 dfs 的时候记录左兄弟节点 pre[i].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef set<int> si;
#define sf(n) scanf("%d",&n)
#define pf(n) printf("%d",n)
#define pfn(n) printf("%d\n",n)
#define pfc(c) printf(c)
#define fi(i,s,t) for(register int i=(s);i<(t);i++)
#define fd(i,s,t) for(register int i=(s)-1;i>=(t);i--)
#define mem(a,c) memset(a,c,sizeof(a))
#define all(x) (x).begin(),(x).end()
#define ft first
#define sd second
#define pb push_back
#define mp make_pair
const int INF=0x3f3f3f3f;
const int MAX=200000+10;
int n,m,u[MAX],p[MAX],q,d[MAX],pre[MAX];
vi v[MAX];
int cnt=0,f[100][MAX];
void dfs(int x){
int tmp=cnt;
fi(i,0,v[x].size()){
dfs(v[x][i]);
}
d[++cnt]=x;
pre[cnt]=tmp;
}
int main(){
freopen("in","r",stdin);
sf(n);sf(m);
u[0]=0;p[0]=0;
fi(i,1,m+1){
sf(u[i]);sf(p[i]);sf(q);
if(q) v[q].pb(i);
else v[0].pb(i);
}
dfs(0);
fi(i,1,cnt)
fi(j,0,n+1){
if(j>=u[d[i]]) f[i][j]=max(f[pre[i]][j],f[i-1][j-u[d[i]]] + u[d[i]] * p[d[i]]);
else f[i][j] = f[pre[i]][j];
}
pf(f[cnt-1][n]);
return 0;
}