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
", f[N]);
	return 0;
}

/*
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

2200
*/
原文地址:https://www.cnblogs.com/Benjamin-cpp/p/11311648.html