P1757 通天之分组背包

题目链接:https://www.luogu.com.cn/problem/P1757

b就是在01背包的基础上对每个物品添加了组数,就变成了分组背包。

考虑到01背包的状态转移方程dp[j]=max(dp[j],dp[j-a[i]]+b[i]),分组背包和它相同.

那么怎么填这个表呢,在01背包中,通过俩层for循环来实现,第一层for是控制第i到n个拿不拿,在分组背包中,这个问题就变成了第i个到n组拿不拿。然后套01背包就可以了。

简单写就是for(i,num)//第1组到第num组

                     for(,)//01背包

                       for(,)

需要注意的是确定每个物品的位置,所以需要开个二维数组来存,f[第几组][第几个]

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x7fffffffffffffff
typedef long long ll;
const double PI=3.1415926535897931;
const long long mod=1e9+7;
const int MA= 1e7+10;
const int ma= 2*1e6+10;
const int few=1e3+10;
using namespace std;
//////////////////////////////////////////////

int dp[ma];
int a[ma];
int b[ma];
int c[ma];
int f[few][few];
int num;
int cnt[ma];
int main()
{
    int m,n;
    cin>>m>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i]>>b[i]>>c[i];
        num=max(num,c[i]);//找最大的组数
        cnt[c[i]]++;统计每个组的数
        f[c[i]][cnt[c[i]]]=i;记录成员的位置,方便后面的访问
    }
    for(int k=1; k<=num; k++)//第1组到第num组
        for(int j=m; j>=0; j--)//01背包
            for(int i=1; i<=cnt[k]; i++)
            {
                int tmp=f[k][i];
                if(j>=a[tmp])
                    dp[j]=max(dp[j],dp[j-a[tmp]]+b[tmp]);//熟悉的状态转移方程
            }
    cout<<dp[m]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Aracne/p/12567636.html