分组背包

洛谷地址:https://www.luogu.com.cn/problem/P1757

P1757 通天之分组背包

题目背景

直达通天路·小 A 历险记第二篇

题目描述

\(01\) 背包问世之后,小 A 对此深感兴趣。一天,小 A 去远游,却发现他的背包不同于 \(01\) 背包,他的物品大致可分为 \(k\) 组,每组中的物品相互冲突,现在,他想知道最大的利用价值是多少。

输入格式

两个数 \(m,n\),表示一共有 \(n\) 件物品,总重量为 \(m\)

接下来 \(n\) 行,每行 \(3\) 个数 \(a_i,b_i,c_i\),表示物品的重量,利用价值,所属组数。

输出格式

一个数,最大的利用价值。

输入输出样例 #1

输入 #1

45 3
10 10 1
10 5 1
50 400 2

输出 #1

10

说明/提示

\(0 \leq m \leq 1000\)\(1 \leq n \leq 1000\)\(1\leq k\leq 100\)\(a_i, b_i, c_i\)int 范围内。

思路:先把所有物品按照它们的组别以它们的下标索引存储在一个二维数组中

之后按照分组背包的模板套即可

#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
typedef long long ll;
ll n,m;
int fz[N][N];#第一个表示组别,第二个表示是这个组别里面的第i个
int cnt[N];#用于计数
int a[N],b[N],x;
ll dp[N];
int t;
int main()
{
    cin>>m>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i]>>b[i]>>x;
        fz[x][cnt[x]]=i;
        t = max(t,x);
        cnt[x]++;
    }
    for(int i=1;i<=t;i++)
    {
        for(int j=m;j>=0;j--)
        {
            for(int k=0;k<cnt[i];k++)
            {
                if(j>=a[fz[i][k]])
                {
                    dp[j]=max(dp[j],dp[j-a[fz[i][k]]]+b[fz[i][k]]);
                }
            }
        }
    }
    cout<<dp[m]<<endl;
    return 0;
}
posted @ 2025-05-20 13:10  屈臣  阅读(19)  评论(0)    收藏  举报