P1064 金明的预算方案
金明的预算方案
思路:
观察题面的描述,不难发现对于每个主件,最多只存在有2个附件,所以我们可以对每一个主件进行暴力枚举。在01背包的for循环中,对于每一个主件,有五种选择:
1.不买该主件。 2.仅买该主件。 3.买主件和附件1. 4.买主件和附件2. 5.买主件以及两个附件。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
//Mystery_Sky
//
#define M 1000010
#define INF 0x3f3f3f3f
#define ll long long
inline int read()
{
int x=0, f=1;
char c = getchar();
while(c < '0' || c >'9') {if(c=='-') f=-1; c=getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c=getchar();}
return x*f;
}
int N, m;
int v[M], q[M], p[M];
int f[32001];
vector <int> root;
vector <int> son[60];
int tot[M], sum;
int new_v[M], new_q[M], new_p[M];
int main() {
N = read(), m = read();
for(int i = 1; i <= m; i++) {
v[i] = read(), p[i] = read(), q[i] = read();
p[i] *= v[i];
if(q[i] == 0) root.push_back(i), sum++;
else tot[q[i]]++, son[q[i]].push_back(i) ;
}
int new_m = 0;
for(int i = 0; i < sum; i++) {
for(int j = N; j >= v[root[i]]; j--) {
f[j] = max(f[j], f[j-v[root[i]]] + p[root[i]]);
if(tot[root[i]] >= 1) {
if(j >= v[root[i]] + v[son[root[i]][0]])
f[j] = max(f[j], f[j-v[root[i]] - v[son[root[i]][0]]] + p[root[i]] + p[son[root[i]][0]]);
}
if(tot[root[i]] >= 2) {
if(j >= v[root[i]] + v[son[root[i]][1]])
f[j] = max(f[j], f[j-v[root[i]] - v[son[root[i]][1]]] + p[root[i]] + p[son[root[i]][1]]);
if(j >= v[root[i]] + v[son[root[i]][0]] + v[son[root[i]][1]])
f[j] = max(f[j], f[j-(v[root[i]] + v[son[root[i]][0]] + v[son[root[i]][1]])] + p[root[i]] + p[son[root[i]][0]] + p[son[root[i]][1]]);
}
}
}
printf("%d\n", f[N]);
return 0;
}
/*
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
2200
*/
唯愿,青春不辜负梦想,未来星辰闪耀