洛谷 金明的预算(依赖背包)

此题第一次遇到没什么思路,现在已经知道是依赖型背包。

对于每个主件,根据组合,如果有n个附件,则搭配附件的话最多可以有(n + 1) * n / 2 种组合(总组合数还要 + 1 主件本身),用每种组合更新当前dp[j](前提:当j >= 当前组合所需要钱数),感觉一般依赖型背包n不会太大,不然讨论的组合数太多......

对于本题,v需要计算处理得到(v实际 = v * p思维点),然后视为普通的01背包递推即可。

还有一个地方用法精炼,annex_w[i][0]记录附件个数,annex_w[i][1], annex_w[i][2]记录相应附件的值。(虽然也可以另开一个一位数组记录每个主件的附件个数)

 复习时自己写了一遍,部分错误,贴两份代码对比思考......

自己代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 65;
const int maxsz = 6e5 + 10;
int main_w[maxn], main_v[maxn];
int annex_w[maxn][3], annex_v[maxn][3];
int dp[maxsz];
int N, m;
int cnt;

int main()
{
    cin >> N >> m;
    cnt = 1;
    int v, p, q;
    for(int i = 0; i < m; i++)
    {
        cin >> v >> p >> q;
        if(q == 0)
        {
            main_w[cnt] = v;
            main_v[cnt] = v * p;
            cnt++;
        }
        else
        {
            annex_w[q][0]++;
            annex_w[q][annex_w[q][0]] = v;
            annex_v[q][annex_w[q][0]] = v * p;
        }
    }

    for(int i = 1; i < cnt; i++)
    {
        for(int j = N; j >= main_w[i]; j--)
        {
            dp[j] = max(dp[j], dp[j - main_w[i]] + main_v[i]);

            if(annex_w[i][0] >= 1 && j >= main_w[i] + annex_w[i][1])
            {
                dp[j] = max(dp[j], dp[j - main_w[i] - annex_w[i][1]] + main_v[i] + annex_v[i][1]);
            }
            if(annex_w[i][0] >= 2 && j >= main_w[i] + annex_w[i][2])
            {
                dp[j] = max(dp[j], dp[j - main_w[i] - annex_w[i][2]] + main_v[i] + annex_v[i][2]);

            }
            if(annex_w[i][0] >= 2 && j >= main_w[i] + annex_w[i][1] + annex_w[i][2])
            {
                dp[j] = max(dp[j], dp[j - main_w[i] - annex_w[i][1] - annex_w[i][2]] + main_v[i] + annex_v[i][1] + annex_v[i][2]);
            }
        }
    }
    cout << dp[N] << endl;
    return 0;
}

题解代码: 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 65;
const int maxsum = 35000;
int main_w[maxn], main_v[maxn];
int annex_w[maxn][3], annex_v[maxn][3];
int dp[maxsum + 10];
int N, m;

int main()
{
    cin >> N >> m;
    int v, p, q;
    int cnt = 1;
    for(int i = 1; i <= m; i++)
    {
        cin >> v >> p >> q;
        if(!q)
        {
            main_w[cnt] = v;
            main_v[cnt] = v * p;
            cnt++;
        }
        else
        {
            annex_w[q][0]++;
            annex_w[q][annex_w[q][0]] = v;
            annex_v[q][annex_w[q][0]] = v * p;
        }
    }
    for(int i = 1; i < cnt; i++)
    {
        for(int j = N; j >= main_w[i]; j--)
        {
            dp[j] = max(dp[j], dp[j - main_w[i]] + main_v[i]);

            if(j >= main_w[i] + annex_w[i][1])
                dp[j] = max(dp[j], dp[j - main_w[i] - annex_w[i][1]] + main_v[i] + annex_v[i][1]);

            if(j >= main_w[i] + annex_w[i][2])
                dp[j] = max(dp[j], dp[j - main_w[i] - annex_w[i][2]] + main_v[i] + annex_v[i][2]);

            if(j >= main_w[i] + annex_w[i][1] + annex_w[i][2])
                dp[j] = max(dp[j], dp[j - main_w[i] - annex_w[i][1] - annex_w[i][2]] + main_v[i] + annex_v[i][1] + annex_v[i][2]);
        }
    }
    cout << dp[N] << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38577732/article/details/89358180