首页 > 代码库 > hdu 3033 I love sneakers!

hdu 3033 I love sneakers!

题目:

        链接:点击打开链接

题意:

        xx喜欢收集鞋子,n,m,k分别表示鞋子的总数,xx的钱和鞋子的品牌数目。然后给出每个鞋子的信息有:a,是那种品牌,b,鞋子的标价,c,收藏鞋子得到的价值。对于一个收藏家来说,每种品牌的鞋子只收集一种,求出xx能够得到的最大的收藏价值。

算法:

        分组背包问题。

思路:

        m总的钱数是背包容量,k品牌数是组数。用数组结构体保存每种鞋子的信息,d[i][j].w表示第i种品牌的鞋子中的第j个鞋子的标价,d[i][j].v表示第i种品牌的鞋子中的第j个鞋子价值。状态转移方程dp[i][j]表示前i组品牌中用掉j钱得到的最大的价值。状态转移可以是前一组少取一个,即dp[i-1][p-d[i][j].w]+d[i][j].v,也可以是当前组少取一种,即dp[i][p-d[i][j].w]+d[i][j].v。初始化第一组置为0,其他组置为负无穷,因为只有上一组达到要求才能进行下一组,每组必须取一个。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

struct node{
    int v;
    int w;
}d[20][110];

int num[20];
int dp[20][10010];

int main()
{
    //freopen("input.txt","r",stdin);
    int n,m,k;
    int a,b,c;
    while(scanf("%d%d%d",&n,&m,&k) != EOF)
    {
        memset(num,0,sizeof(num));
        memset(dp,-1,sizeof(dp));
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            d[a][num[a]].w = b;
            d[a][num[a]].v = c;
            num[a]++;//num[a]表示第a组的鞋的个数
        }
        memset(dp[0],0,sizeof(dp[0]));
        for(int i=1; i<=k; i++)
        {
            for(int j=0; j<num[i]; j++)
            {
                for(int p=m; p>=d[i][j].w; p--)
                {
                     if(dp[i-1][p-d[i][j].w] != -1)
                        dp[i][p] = max(dp[i][p],dp[i-1][p-d[i][j].w]+d[i][j].v);
                    if(dp[i][p-d[i][j].w] != -1)
                        dp[i][p] = max(dp[i][p],dp[i][p-d[i][j].w]+d[i][j].v);
                }
            }
        }
        if(dp[k][m] == -1)
            printf("Impossible\n");
        else
            printf("%d\n",dp[k][m]);
    }
    return 0;
}