1086超市购物(分组背包)

1086: 超市购物

Time Limit: 1 Sec  Memory Limit: 128 MB SUBMIT: 122  Solved: 48 [SUBMIT] [STATUS]

Description

        上次去超市扫荡回来的东西用完了,Staginner又得跑超市一趟,出发前他列了一张购物清单,打算去买K种不同的商品,每种买一件。到了超市,Staginner发现每种商品有N个品牌,每个品牌此商品的价格为Vi,对Staginner的作用值为Wi,他会从这N个品牌里面挑一个品牌买。这时,Staginner突然想起出门时只带了M元钱,又懒得去取钱了,所以不一定能买完K种商品,只好尽可能地让买的东西对自己的总作用值ans最大。

Input

多组样例。

    第一行两个整数K,M代表Staginner想买的不同种类商品的数目和他带的钱 (0 < K <= 30, 0 < M <= 2000)
    以下输入分为K个部分,代表K种商品。
    每个部分第一行为一个数字N,代表第k种商品的N个品牌,N不大于10。之后跟着N行,每行两个数字,代表物品的价格Vi和作用值Wi。其中 0 < Vi < M。

Output

输出Case #: 最大总作用值,每两个样例之间有一个空行。

Sample Input

3 100

3

50 600

20 700

30 800		

2

30 500

40 600	

1

60 200



2 500

2

200 1000

260 1200

1

280 300

Sample Output

Case 1: 1400



Case 2: 1300

 

这是中南大学OJ上的一道典型的分组背包问题的题型。分组背包的核心其实还是01背包问题。只是做了一点点转换。

解决办法:

 for(i=0;i<K;i++)   //遍历每一类商品
   for(j=M;j>=0;j--)  //将每一个分组当做一次01背包 ,故计算顺序为M递减 
        for(u=0;u<a[i];u++) //遍历第i类中没个品牌
         if(j-v[i][u]>=0)
            f[j]=(f[j]>f[j-v[i][u]]+w[i][u] ? f[j] : f[j-v[i][u]]+w[i][u]);  //01背包的核心思想

View Code
#include<stdio.h>

#include<string.h>

int main()

{

    int K,M,i,j,u,t=0;

    int a[31],v[31][11],w[31][11],f[2001];

    while(scanf("%d %d",&K,&M)==2)

    {

        t++;

        memset(f,0,sizeof(f));

        for(i=0;i<K;i++)

        {

            scanf("%d",&a[i]);

            for(j=0;j<a[i];j++)

                scanf("%d %d",&v[i][j],&w[i][j]);

        }

        for(i=0;i<K;i++)

        {

            for(j=M;j>=0;j--)

            {

                for(u=0;u<a[i];u++)

                {

                    if(j-v[i][u]>=0)

                        f[j]=(f[j]>f[j-v[i][u]]+w[i][u] ? f[j] : f[j-v[i][u]]+w[i][u]);

                }

            }

        }

        printf("Case %d: %d\n\n",t,f[M]);

    }

    return 0;

}

 

你可能感兴趣的:(分组)