#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int M =110;
typedef struct{
int volum;
int val;
}Data;
Data dat[M][M]; // dat[i][j] 第i组种物品中第j件的数据
int dp[M][11000]; // dp[i][j] 前i组物品 花费不大于j的最大价值
int l[M]; // l[i] 第i组物品的数量
int main()
{
int n,m,k;
while(cin>>n>>m>>k)
{
memset(l,0,sizeof(l));
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
l[a]++;
dat[a][l[a]].val=c;
dat[a][l[a]].volum=b;
}
memset(dp,-1,sizeof(dp));// 保证对第i组操作时 前i-1组的物品至少都取了一件
memset(dp[0],0,sizeof(dp[0])); // 前0组
for(int k1=1;k1<=k;k1++) // dp[k][j] =max(dp[k-1][j-c[i]]+w[i],dp[k][j-c[i]]+w[i]);
{ // 第k组只选了一件 第k组至少选一件
for(int i=1;i<=l[k1];i++)// 对每组进行(至少选一件)的01背包
{
for(int j=m;j>=dat[k1][i].volum;j--)// dp[k][i][j] 优化掉前i件 所以逆推
{
if(dp[k1][j-dat[k1][i].volum]!=-1)
{
dp[k1][j]=max(dp[k1][j],dp[k1][j-dat[k1][i].volum]+dat[k1][i].val);
}
if(dp[k1-1][j-dat[k1][i].volum]!=-1) //!=-1 如果选一件 则前K1-1组要符合条件 (即前K1-1组都至少都选了一件)
{
dp[k1][j]=max(dp[k1][j],dp[k1-1][j-dat[k1][i].volum]+dat[k1][i].val);
}
//因为物品体积可能为0 所以两个if 顺序不能变
// 若调换 则dp[k][j]= dp[k][j-0]+w= dp[k-1][j-0]+w +w 同一件物品被放了两次
}
}
}
if(dp[k][m]!=-1)
cout<<dp[k][m]<<endl;
else
{
cout<<"Impossible"<<endl;
}
}
return 0;
}
hdu 3033 分组背包+01背包
最新推荐文章于 2021-05-17 21:13:28 发布