题意
m
m
元钱, 双鞋子,每双鞋子都有一个品牌,费用,价值,共
k
k
个品牌,要求每种品牌至少买一双鞋子且不能买两双一样的鞋子,求最大价值。
1≤m≤10000
1
≤
m
≤
10000
1≤k≤10
1
≤
k
≤
10
思路
把每种品牌看成一个阶段,把每双鞋子当物品进行01背包,注意要转移这一阶段和上一阶段的值,可以改为滚动优化。
代码
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
typedef long long LL;
using namespace std;
int dp[2][10003];
struct shoes
{
int a,c,v;
void Read(){scanf("%d%d%d",&a,&c,&v);}
bool operator <(const shoes &_)const
{
return a<_.a;
}
}s[10003];
int main()
{
int n,m,p;
while(~scanf("%d%d%d",&n,&m,&p))
{
FOR(i,1,n)s[i].Read();
sort(s+1,s+1+n);
int k=1,ans=-1;
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
FOR(i,1,p)
{
memset(dp[i&1],-1,sizeof(dp[i&1]));
for(;s[k].a==i;k++)
DOR(j,m,s[k].c)
{
if(~dp[i&1][j-s[k].c])
dp[i&1][j]=max(dp[i&1][j],dp[i&1][j-s[k].c]+s[k].v);
if(~dp[~i&1][j-s[k].c])
dp[i&1][j]=max(dp[i&1][j],dp[~i&1][j-s[k].c]+s[k].v);
//由于费用可能是0,所以这两次转移的顺序不能颠倒,否则可能会同时买了两双k鞋
}
}
FOR(i,0,m)ans=max(ans,dp[p&1][i]);
if(~ans)printf("%d\n",ans);
else printf("Impossible\n");
}
return 0;
}