金明的预算方案

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]);
}

 

posted on 2022-08-26 16:05  樵风  阅读(106)  评论(0)    收藏  举报