题目
分析
f[i]表示i的钱内能得到的最大价值
g[j]表示在选了某个主件下,j的钱内得到的最大价值
则状态转移方程为:
g[i]=max(g[i],g[i-a[j].price]+a[j].value) (其中j为i的附件),
f[i]=max(f[i],g[i])
AC代码
#include <iostream>
#include <cstdio>
using namespace std;
int f[40000], g[40000];
struct node {
int price, value, team;// 价格、价值、属性(team = 0该物品为主件,否则为附件且其值为附件编号)
}a[100];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &a[i].price, &a[i].value, &a[i].team);
a[i].value *= a[i].price;// 等效价值
}
for (int i = 1; i <= m; i++)
{
if (a[i].team == 0) // 是主件
{
for (int j = 1; j < a[i].price; j++)
{
g[j] = 0;// 初始化
}
// 对每组物品的主、附件进行 DP
for (int j = a[i].price; j <= n; j++)
{
g[j] = f[j - a[i].price] + a[i].value;
}
for (int j = 1; j <= m; j++)
{
if (a[j].team == i)
{
for (int k = n; k >= a[i].price + a[j].price; k--)
{
g[k] = max(g[k], g[k - a[j].price] + a[j].value);
}
}
}
for (int j = a[i].price; j <= n; j++)
{
f[j] = max(f[j], g[j]);
}
}
}
printf("%d", f[n]);
return 0;
}