poj 1170 多重背包

转载 2012年03月22日 02:05:14

还是看了这位大牛的

http://www.chenyajun.com/2010/05/30/4597

题目大意:其实就是个全背包问题~~动态规划

给出每种物品的单价,和个数,然后给出这些物品的组合的优惠策略,要你求出购买这些物品的最小消费。

《编程之美》里有个买书的问题,跟这题很像。

这题难就难在动态规划的维度过多,比如就有3个品种的物品,有种打折策略

dp[i][j][k]表示物品0有i个,物品1有j个,物品2有k个的最小花费, 一种打折策略为物品0, a个与物品1, b个, 与物品 2,c个一起买共花费cost

dp[i][j][k] = dp[i-a][j-b][k-c] + cost,求这些打折策略里面最小的

这个商品的第几维不好去确定,要一个个的去枚举,很麻烦。。。。

考虑状态压缩策略,把每种商品对应的一个维度上去,由于每种商品的个数不超过5个,所以就像对应十进制一样,把它对应到6进制上,比如0商品x1个,1商品x2个,3商品x3个...那么压缩成x1 * 6的0次方 + x2 *  6的一次方 + x3 * 6的2次方 + 。。。 + xn * 6的n-1次方。 这样得到的状态值也可以反过来拆分到各商品分别有多少个。

 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;

struct node
{
    int num, price;
};

int b, s, st, dp[56656];
node basket[5], offer[100];
map<int, int> dic;   //这个用来商品编码映射对应到6进制的第几位
int state[] = {1, 6, 36, 216, 1296, 7776, 46656};

inline bool check(int s1, int s2);//这个是用来计算状态s1和状态s2对应的每种商品的和是否超过了篮子里面的每种商品的个数
inline int cal(int sv);//这个是用来计算状态sv对应的商品花费总和

int main()
{
    memset(dp, -1, sizeof(dp));
    dp[0] = 0;
    st = 0;
    int index;
    scanf("%d", &b);
    for(int i = 0; i < b; i++)
    {
        int c;
        scanf("%d %d %d", &c, &basket[i].num, &basket[i].price);
        st += state[i] * basket[i].num;//求整个篮子里商品和对应的六进制
        dic[c] = i;
    }
    scanf("%d", &s);
    for(int i = 0; i < s; i++)
    {
        offer[i].num = 0;
        int n;
        scanf("%d", &n);
        for(int j = 0; j < n; j++)
        {
            int c, nu;
            scanf("%d %d", &c, &nu);
            index = dic[c];
            offer[i].num += state[index] * nu;//第i种打折策略对应的六进制状态
        }
        scanf("%d", &offer[i].price);
    }
    for(int i = 0; i < s; i++)
    {
        for(int j = 0; j <= st; j++)
        {
            if(dp[j] != -1)
            {
                if(j + offer[i].num <= st && check(j, offer[i].num))//相当于0/1背包问题,j状态表示对应选好的几种商品的和,与第i中打折策略的商品个数的和不超过总的商品个数,并且确定j状态的对应的第k种商品个数和和打折对应的第k种商品个数和不超过篮子里第k种商品的个数
                {
                    if(dp[j + offer[i].num] == -1)
                        dp[j + offer[i].num] = dp[j] + offer[i].price;
                    else
                        dp[j + offer[i].num] = min(dp[j + offer[i].num], dp[j] + offer[i].price);
                }
            }
        }
    }
    int ans = 0x7fffffff;
    for(int i = 0; i <= st; i++)
    {
        if(dp[i] != -1)
            ans = min(ans, dp[i] + cal(st - i));//求出最小的花费
    }
    printf("%d\n", ans);
    return 0;
}

inline bool check(int s1, int s2)
{
    for(int i = 0; i < b; i++)
    {
        if((s1 % 6 + s2 % 6) > basket[i].num)
            return false;
        s1 /= 6;
        s2 /= 6;
    }
    return true;
}

inline int cal(int sv)
{
    int sum = 0;
    for(int i = 0; i < b; i++)
    {
        sum += (sv % 6) * basket[i].price;
        sv /= 6;
    }
    return sum;
}


 

POJ 多重背包专题

POJ 1014  Dividing 这道题用背包做有两种解法,一种是拆分法,另一种是很神的O(VN)的DP法。 拆分法: #include #include #include #in...
  • sdj222555
  • sdj222555
  • 2011年10月26日 21:11
  • 1382

poj1742 多重背包的可行性问题

http://poj.org/problem?id=1742 Description People in Silverland use coins.They have coins of v...
  • u013573047
  • u013573047
  • 2015年03月18日 21:17
  • 1348

poj1170 状态压缩

因为每种物品最多五个,总共五种物品,所以可以将状态存为6进制的整数。 先对每一种special offer进行dp, 转移方程为  dp[ i + offfer[k].stt ] = MIN( dp...
  • Non_Cease
  • Non_Cease
  • 2011年10月20日 22:22
  • 949

POJ 1170 Shopping Offers 状态压缩dp+完全背包

题意: 有n种物品需要你去购买,每种物品购买num【i】个。(1 ) 当然提供s种优惠:购买商家规定的组合商品的价格为 s【i】 2 7 3 2 8 2 5 2 1 7 3 5 2 7 1 ...
  • zp___waj
  • zp___waj
  • 2017年04月15日 20:50
  • 361

poj 1787 多重背包记录路径

第一道记录路径的题目 Charlie's Change Time Limit: 1000MS   Memory Limit: 30000K Total Submiss...
  • haha593572013
  • haha593572013
  • 2013年08月19日 18:49
  • 540

poj 1276 多重背包+二进制优化+单调队列优化

Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27570   ...
  • cokomowang
  • cokomowang
  • 2014年08月28日 13:59
  • 459

poj-1014 多重背包问题

Dividing     题意:有一堆大理石,每个石头的价值在1-6之间,每种价格的石头有多个。现在要求将这堆石头分成两份,使得两份的总价值相同,回答是否存在一种方法将可以实现划分。     这是一道...
  • more_ugly_less_bug
  • more_ugly_less_bug
  • 2017年07月06日 10:22
  • 357

POJ 1742 Coins(多重背包变型,楼教主男人八题)

Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 34853   Accepte...
  • hhu1506010220
  • hhu1506010220
  • 2016年08月31日 17:04
  • 307

poj2392 多重背包问题

http://poj.org/problem?id=2392 Description The cows are going to space! They plan to achieve o...
  • u013573047
  • u013573047
  • 2014年11月16日 20:19
  • 1059

poj1170(状态压缩dp)

链接:点击打开链接 题意:给定一个含有n种商品的订单,给出订单内每个物品的初始价格和需要购买的数量,再给出m种套餐,这些组合会得到便宜的价格,最后怎样搭配使得总价格最少。 代码: #include ...
  • stay_accept
  • stay_accept
  • 2016年04月15日 20:42
  • 322
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj 1170 多重背包
举报原因:
原因补充:

(最多只允许输入30个字)