HDU-3033 I love sneakers!(01背包)

题意

m 元钱, n 双鞋子,每双鞋子都有一个品牌,费用,价值,共 k 个品牌,要求每种品牌至少买一双鞋子且不能买两双一样的鞋子,求最大价值。
1 n 100
1 m 10000
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;
}

猜你喜欢

转载自blog.csdn.net/paulliant/article/details/80814317