P1064 金明的预算方案
曾经吓死我的背包题
一看就知道是背包啊, 但是不是一般的01背包。
但说到底也就5种决策:
-
不取主件
-
只取主件,不取任何附件
-
取主件,取附件1,不取附件2
-
取主件,取附件2,不取附件1
-
全都取
按照这5种决策,在她们各自合法的情况下转移即可解决。
代码:
#include<cstdio>
#include<vector>
#include<algorithm>
const int maxn = 65, maxm = 32005;
int dp[maxm];
int v[maxn], p[maxn], q[maxn];
std::vector<int> vec[maxn];
int n, m;
int main()
{
scanf("%d%d", &m, &n);
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d", &v[i], &p[i], &q[i]);
if(q[i]) vec[q[i]].push_back(i);
}
for(int i = 1; i <= n; i++)
{
if(q[i]) continue;
for(int j = m; j >= v[i]; j--)
{
dp[j] = std::max(dp[j], dp[j - v[i]] + v[i] * p[i]);
int siz = vec[i].size();
if(siz == 1)
{
int temp = vec[i][0];
if(j >= v[i] + v[temp]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp]] + v[i] * p[i] + v[temp] * p[temp]);
}
else if(siz == 2)
{
int temp1 = vec[i][0], temp2 = vec[i][1];
if(j >= v[i] + v[temp1]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp1]] + v[i] * p[i] + v[temp1] * p[temp1]);
if(j >= v[i] + v[temp2]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp2]] + v[i] * p[i] + v[temp2] * p[temp2]);
if(j >= v[i] + v[temp1] + v[temp2]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp1] - v[temp2]] + v[i] * p[i] + v[temp1] * p[temp1] + v[temp2] * p[temp2]);
}
}
}
printf("%d\n", dp[m]);
return 0;
}