andre_joy

导航

hdu 3033

地址:http://acm.hdu.edu.cn/showproblem.php?pid=3033

题意:一个人买商品,必须每个种类的商品至少买一件,同时保证买到的价值尽可能大,如果不能满意,输出Impossible。

mark:分组背包的变种,普通分组背包是一个组里面最大取一件,这题是至少取一件。

    设计状态dp[i][j]代表前i组容量为j的最大价值。由于一组里面有多个物品,所以状态转移可以是前一组少取一个,即dp[i-1][p-g[i][j].v]+g[i][j].w,也可以是当前组之前去过的少取一种,即dp[i][p-g[i][j].v]+g[i][j].w。

    网上有些解题报告是错误的解法,这题dp初始化的时候要初始化为负无穷,因为这题要求的是上一组恰好达到的状态才能转移到这一组来,因为每一组至少得去一个。当然可以初始化为-1,每次判断一下是不是-1就行。

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct
{
    int v,w;
}goods;

const int N = 110;
const int M = 10010;
int n,m,k;
goods g[15][N];
int num[15];
int dp[15][M];

int min(int a, int b) {return a < b ? a : b;}
int max(int a, int b) {return a > b ? a : b;}

int main()
{
    int i,j;
    while(~scanf("%d%d%d", &n, &m, &k))
    {
        int aa,bb;
        memset(num, 0, sizeof(num));
        for(i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &j, &aa, &bb);
            g[j][num[j]].v = aa;
            g[j][num[j]].w = bb;
            num[j]++;
        }
        memset(dp, -1, sizeof(dp));
        memset(dp[0], 0, sizeof(dp[0]));
        for(i = 1; i <= k; i++)
        {
            for(j = 0; j < num[i]; j++)
                for(int p = m; p >= g[i][j].v; p--)
                {
                    if(dp[i][p-g[i][j].v] != -1) dp[i][p] = max(dp[i][p], dp[i][p-g[i][j].v]+g[i][j].w);
                    if(dp[i-1][p-g[i][j].v] != -1) dp[i][p] = max(dp[i][p], dp[i-1][p-g[i][j].v]+g[i][j].w);
                }
        }
        if(dp[k][m] < 0) puts("Impossible");
        else printf("%d\n", dp[k][m]);
    }
    return 0;
}

posted on 2012-09-28 21:41  andre_joy  阅读(359)  评论(0编辑  收藏  举报