01背包变式

金明的预算方案

https://ac.nowcoder.com/acm/problem/16671

01背包的变式题

思路:对于经典的01背包本题的不同之处在于多了只有当主件购买时才可以购买附件,
并且每个主件最多只有2个附件。思考一下不难发现,将原本的01背包的决策(选或不选)
变为现在的决策(不选主件|选主件|选主件+附件1|选主件+附件2|选主件+附件1+附件2)。
dp[i][j]表示在前i件物品当金钱为j时的最大价值,如果第i件物品为附件则dp[i][j]=dp[i-1][j](略过
该判断附件的情况在主件时一并判断了)。
接下来是判断针对dp[i][j]判断5个决策。

int c[Max],v[Max],f[Max];//分别存储价格、重要程度、所对应主件
vector<int> vec[Max];//存储主件对应的附件</int>

dp[i][j] = dp[i - 1][j];
if (f[i] != 0) continue;
if (j >= c[i]) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + v[i] * c[i]); //决策:选择要主件和不要主件
for (int k = 0; k < vec[i].size(); k++)
{
if (j >= c[i] + c[vec[i][k]]) dp[i][j] = max(dp[i][j], dp[i - 1][j - c[i] - c[vec[i][k]]] + v[i] * c[i] + v[vec[i][k]] * c[vec[i][k]]);
} //决策:根据附件的的多少选择要主键+一个附件
if (vec[i].size() == 2 && j >= c[i] + c[vec[i][0]] + c[vec[i][1]])
{
dp[i][j] = max(dp[i][j], dp[i - 1][j - c[i] - c[vec[i][0]] - c[vec[i][1]]] + c[i] * v[i] + c[vec[i][1]] * v[vec[i][1]] + c[vec[i][0]] * v[vec[i][0]]);
} //决策:如果有两个附件则判断两个附件+主件一起购买的情况

当然可以有滚动数组优化为一维,看数据不大就直接开2维了。

AC代码

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<algorithm>
#include<set>
#include<cmath>
#include<iomanip>
#include<memory.h>
#include<queue>
#define pii pair<int,int>
using namespace std;
typedef long long ll;
const int Max = 1e5 + 5;
int lst[Max];
int dp[65][Max];
int c[Max],v[Max],f[Max];
vector<int> vec[Max];

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &c[i], &v[i], &f[i]);
        vec[f[i]].push_back(i);
    }
    for (int i = 1; i <= m; i++)
    {
        for (int j = 0; j <= n; j++)
        {
            dp[i][j] = dp[i - 1][j];
            if (f[i] != 0) continue;
            if (j >= c[i]) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + v[i] * c[i]);
            for (int k = 0; k < vec[i].size(); k++)
            {
                if (j >= c[i] + c[vec[i][k]]) dp[i][j] = max(dp[i][j], dp[i - 1][j - c[i] - c[vec[i][k]]] + v[i] * c[i] + v[vec[i][k]] * c[vec[i][k]]);
            }
            if (vec[i].size() == 2 && j >= c[i] + c[vec[i][0]] + c[vec[i][1]])
            {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - c[i] - c[vec[i][0]] - c[vec[i][1]]] + c[i] * v[i] + c[vec[i][1]] * v[vec[i][1]] + c[vec[i][0]] * v[vec[i][0]]);
            }
        }
    }
    cout << dp[m][n] << endl;
}
全部评论

相关推荐

昨天 16:53
郑州大学 Java
点赞 评论 收藏
分享
2024-12-07 21:27
重庆邮电大学 Java
疯狂学习a:好看,想要,我是学生能送我么😋
投递大疆等公司8个岗位 晒一晒你收到的礼盒
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务