COJ1086 分组01背包

1086: 超市购物

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 183  Solved: 73
[Submit][Status][Web Board]

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
 
一开始知道是01背包问题,但一直纠结于如何有效的在每类商品里选择一种,想暴力枚举。。算一下几乎是TLE的命,。。。所以后来百度一下,知道了分组背包这种写法。,分组背包核心方程任然是f[i]=max(f[i],f[i-v[i]]+w[i])
但写法上的不同在于
简单的01背包是
for (每件物品)
 for(遍历背包容量)
 {核心方程};
而分组背包的写法是
for(每类物品)
 for(遍历背包容量)
  for(遍历某类物品的所以)
   {核心方程}
细细想一下就发现,部分背包,在遍历某一类商品的时候,就把当前类的 max某一件最优给存贮下来了。。直接起到了从每类商品中挑选一件出来的作用
 
#include <iostream>
#include <cstring>
using namespace std;
int money[2005];
int v[35][15];
int w[35][15];
int num[35];
int main()
{
    int k,m;int cur=1;
    while (cin>>k>>m)
    {
        memset(money,0,sizeof (money[0])*(m+2));
        for (int i=0;i<k;i++)
        {
            cin>>num[i];
            for (int j=0;j<num[i];j++)
            {
                cin>>v[i][j]>>w[i][j];
            }
        }
        for (int q=0;q<k;q++)
        {
           for(int t=m;t>=0;t--)
            for (int r=0;r<num[q];r++)
             if (t-v[q][r]>=0)
             money[t]=(money[t]>money[t-v[q][r]]+w[q][r]) ? money[t] : money[t-v[q][r]]+w[q][r];
        }
      cout<<"Case "<<cur++<<": "<<money[m]<<endl;
      cout<<endl;
    }
return 0;
}
 
 
原文地址:https://www.cnblogs.com/kkrisen/p/3047626.html