金明的预算方案
P1064 [NOIP2006 提高组] 金明的预算方案 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 从普通01背包选还是不选变成选不选主,选不选主+1,选不选主+2的几种情况
- main用于存主的重量和贡献,fu用于存附属的,cnt用作记录第i个主有几个附属,好存到fu里面
- 两层for循环是标准的01背包模板(为什么要逆序,为什么正序后就不是01背包而变成完全背包)
- if用于判断能否装的下一个主若干个附属,如果可以装的下就尝试装下并更新
#include <bits/stdc++.h>
using namespace std;
#define N 1e5
#define INF 2e9
#define MAX 100000
// https://www.luogu.com.cn/problem/P1064
int n, m;
int main_wei[MAX], main_val[MAX], cnt[MAX], fu_wei[MAX][3], fu_val[MAX][3];
int main()
{
cin >> n >> m;
for (int i = 1, a, b, c; i <= m; i++)
{
scanf("%d%d%d", &a, &b, &c);
if (!c)
{
main_wei[i] = a;
main_val[i] = a * b;
}
else
{
cnt[c]++;
fu_wei[c][cnt[c]] = a;
fu_val[c][cnt[c]] = a * b;
}
}
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= m; i++)
{
for (int j = n; j >= main_wei[i]; j--)
{
cnt[j] = max(cnt[j], cnt[j - main_wei[i]] + main_val[i]);
if (j >= main_wei[i] + fu_wei[i][1])
cnt[j] = max(cnt[j], cnt[j - main_wei[i] - fu_wei[i][1]] + main_val[i] + fu_val[i][1]);
if (j >= main_wei[i] + fu_wei[i][2])
cnt[j] = max(cnt[j], cnt[j - main_wei[i] - fu_wei[i][2]] + main_val[i] + fu_val[i][2]);
if (j >= main_wei[i] + fu_wei[i][1] + fu_wei[i][2])
cnt[j] = max(cnt[j], cnt[j - main_wei[i] - fu_wei[i][1] - fu_wei[i][2]] + main_val[i] + fu_val[i][1] + fu_val[i][2]);
}
}
printf("%d", cnt[n]);
}