Codevs1155 金明的预算方案 ——2006年NOIP全国联赛提高组
由于至多有2个附件,直接手动枚举就好了。
dp时:
- 如果当前物品是附件, 跳过
- 如果当前物品时主件
- 只选这个主件,不选它的附件
- 当这个主件有附件时, 选它和它的第一个主件
- 当这个主件有2个附件时, 选它和它的第二个主件
- 当这个主件有2个附件时, 选它和它的所有附件
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
#define MAXN (60+6)
#define MAXV (32000+32)
struct item{
int v, p, q;
}l[MAXN];
int dp[MAXV];
vector <int> q[MAXN];
int main()
{
int V, n;
cin >> V >> n;
for(int i = 1; i <= n; i ++)
{
scanf("%d%d%d", &l[i].v, &l[i].p, &l[i].q);
if(l[i].q) q[l[i].q].push_back(i);
}
for(int i = 1; i <= n; i ++)
{
if(l[i].q) continue;
for(int j = V; j >= 0; j --)
{
// 只选主件
if(j >= l[i].v)
dp[j] = max(dp[j], dp[j - l[i].v] + l[i].v*l[i].p);
//只选第一件
if(q[i].size() && j >= l[i].v + l[q[i][0]].v)
dp[j] = max(dp[j], dp[j - (l[i].v + l[q[i][0]].v)] + l[i].v*l[i].p + l[q[i][0]].v*l[q[i][0]].p);
//只选第二件
if(q[i].size() > 1 && j >= l[i].v + l[q[i][1]].v)
dp[j] = max(dp[j], dp[j - (l[i].v + l[q[i][1]].v)] + l[i].v*l[i].p + l[q[i][1]].v*l[q[i][1]].p);
//全选
if(q[i].size() > 1 && j >= l[i].v + l[q[i][0]].v + l[q[i][1]].v)
dp[j] = max(dp[j], dp[j - (l[i].v + l[q[i][0]].v + l[q[i][1]].v)] + l[i].v*l[i].p + l[q[i][0]].v*l[q[i][0]].p + l[q[i][1]].v*l[q[i][1]].p);
}
}
cout << dp[V];
return 0;
}
另:(精简不了多少……)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
#define MAXN (60+6)
#define MAXV (32000+32)
int dp[MAXV];
struct item{
int v, p, q;
}l[MAXN];
vector <int> q[MAXN];
int main()
{
int V, n;
cin >> V >> n;
for(int i = 1; i <= n; i ++)
{
scanf("%d%d%d", &l[i].v, &l[i].p, &l[i].q);
if(l[i].q) q[l[i].q].push_back(i);
}
for(int i = 1; i <= n; i ++)
{
if(l[i].q) continue; //如果是附件
for(int j = V; j >= 0; j --)
{
int lson, rson;
if(q[i].size()) lson = q[i][0];// 假设附件为 儿子
if(q[i].size() > 1) rson = q[i][1];
//只选主件
if(j >= l[i].v)
dp[j] = max(dp[j], dp[j-l[i].v] + l[i].v*l[i].p);
//选主件和第一个附件
if(q[i].size() > 0 && j >= l[i].v + l[lson].v)
dp[j] = max(dp[j], dp[j - (l[i].v + l[lson].v)] + l[i].v*l[i].p + l[lson].v*l[lson].p);
//选主件和第二个附件
if(q[i].size() > 1 && j >= l[i].v + l[rson].v)
dp[j] = max(dp[j], dp[j - (l[i].v + l[rson].v)] + l[i].v*l[i].p + l[rson].v*l[rson].p);
//全选
if(q[i].size() > 1 && j >= l[i].v + l[lson].v + l[rson].v)
dp[j] = max(dp[j], dp[j - (l[i].v + l[lson].v + l[rson].v)] + l[i].v*l[i].p + l[lson].v*l[lson].p + l[rson].v*l[rson].p);
}
}
cout << dp[V];
return 0;
}