poj - 1170 - Shopping Offers(减少国家dp)

意甲冠军:b(0 <= b <= 5)商品的种类,每个人都有一个标签c(1 <= c <= 999),有需要购买若干k(1 <= k <=5),有一个单价p(1 <= p <= 999)。有s(0 <= s <= 99)。问完毕採购最少须要多少钱。

题目链接:http://poj.org/problem?id=1170

——>>已有b种物品,再将每种优惠分别看成一种新物品,剩下就是全然背包问题了。。

设dp[i]表示购买状态为 i 时的最少花费(关于购买状态:00032表示第0种物品买2个,第1种物品买3个)。则状态转移方程为:

dp[i + product[j].nState] = min(dp[i + product[j].nState], dp[i] + product[j].nPrice)(j是枚举各种物品的物品下标);

#include <cstdio>
#include <cstring>
#include <algorithm>

using std::min;

const int MAXN = 5 + 1;
const int MAXS = 6 * 6 * 6 * 6 * 6;
const int MAX_SIX = 6;
const int MAX_ID = 999 + 1;
const int MAX_OFFER = 99 + 1;

struct PRODUCT
{
    int nId;
    int nNum;
    int nPrice;
    int nState;
} product[MAXN + MAX_OFFER];

int nType;
int dp[MAXS];
int nTargetState;
int nSixPow[MAX_SIX];
int nId2Bit[MAX_ID];

void Init()
{
    nType = 0;
    nTargetState = 0;
}

void GetSixPow()
{
    nSixPow[0] = 1;
    for (int i = 1; i < MAX_SIX; ++i)
    {
        nSixPow[i] = nSixPow[i - 1] * 6;
    }
}

void CompletePack()
{
    memset(dp, 0x3f, sizeof(dp));
    dp[0] = 0;
    for (int i = 0; i < nTargetState; ++i)
    {
        for (int j = 0; j < nType; ++j)
        {
            if (i + product[j].nState > nTargetState) continue;
            dp[i + product[j].nState] = min(dp[i + product[j].nState], dp[i] + product[j].nPrice);
        }
    }
    printf("%d\n", dp[nTargetState]);
}

int main()
{
    int b, s, n;

    GetSixPow();
    while (scanf("%d", &b) == 1)
    {
        Init();
        for (int i = 0; i < b; ++i)
        {
            scanf("%d%d%d", &product[i].nId, &product[i].nNum, &product[i].nPrice);
            product[i].nState = nSixPow[i];
            nTargetState += nSixPow[i] * product[i].nNum;
            nId2Bit[product[i].nId] = i;
        }
        scanf("%d", &s);
        for (int i = 0; i < s; ++i)
        {
            int nId, nCnt;
            product[b + i].nState = 0;
            scanf("%d", &n);
            for (int j = 0; j < n; ++j)
            {
                scanf("%d%d", &nId, &nCnt);
                product[b + i].nState += nSixPow[nId2Bit[nId]] * nCnt;
            }
            scanf("%d", &product[b + i].nPrice);
        }
        nType = b + s;
        CompletePack();
    }
    return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-08-27 08:00:58

poj - 1170 - Shopping Offers(减少国家dp)的相关文章

POJ - 1170 Shopping Offers (五维DP)

题目大意:有一个人要买b件商品,给出每件商品的编号,价格和数量,恰逢商店打折.有s种打折方式.问怎么才干使买的价格达到最低 解题思路:最多仅仅有五种商品.且每件商品最多仅仅有5个,所以能够用5维dp来表示.每一个维度都代表一件商品的数量 打折的方式事实上有b + s种.将每种商品单件卖的也算一种打折方式 这题有个坑点,就是b或者s有可能为0 #include<cstdio> #include<cstring> #include<algorithm> #include&l

背包系列练习( hdu 2844 Coins &amp;&amp; hdu 2159 &amp;&amp; poj 1170 Shopping Offers &amp;&amp; hdu 3092 Least common multiple &amp;&amp; poj 1015 Jury Compromise)

作为一个oier,以及大学acm党背包是必不可少的一部分.好久没做背包类动规了.久违地练习下-.- dd__engi的背包九讲:http://love-oriented.com/pack/ 鸣谢http://blog.csdn.net/eagle_or_snail/article/details/50987044,这里有大部分比较有趣的dp练手题. hdu 2844 Coins 多重背包 就是一个10w的多重背包,每个物品的cost同时也作为value去做背包,我们求的是每个容量下的价值,所以没

poj - 1170 - Shopping Offers(状态压缩dp)

题意:b(0 <= b <= 5)种物品,每种有个标号c(1 <= c <= 999),有个需要购买的个数k(1 <= k <=5),有个单价p(1 <= p <= 999),有s(0 <= s <= 99)种组合优惠方案,问完成采购最少需要多少钱. 题目链接:http://poj.org/problem?id=1170 -->>已有b种物品,再将每种优惠分别看成一种新物品,剩下就是完全背包问题了.. 设dp[i]表示购买状态为 i

poj 1185 火炮 (减少国家DP)

火炮 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19690   Accepted: 7602 Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队. 一个N*M的地图由N行M列组成.地图的每一格可能是山地(用"H" 表示).也可能是平原(用"P"表示).例如以下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不可以部署炮兵部队):一支炮兵部队在地图上的攻

POj 1170 Shopping Offers(变形背包+进制优化) 100

商店买东西会有优惠政策,使用优惠政策使顾客花的钱尽可能的少. 这道题很有现实背景啊,起初看这道题想的是用规则去优化各种组合情况的物品,并没有想到用背包.因为没有做过"规则"这种物品 还有一点就是接收输入信息的时候若用高维数组很难控制,当时竟然写出了int (*it)[5][5][5][5] 这种东西. 这时,进制优化发挥作用了,其思想类似于康托展开,且因为这个问题并不是直接将位置映射到数集,而是各个不同物品的映射.六进制就够用了.将各个物品映射到一个六进制数字中的每一位,一位上的数字0

【POJ 1170】 Shopping Offers [动态规划 状态压缩 背包][离散化]

POJ - 1170 Shopping Offers 放假打题 sufu 看完题我是懵比的 这....  emmmmm   瓜想了半个小时之后我选择狗带 然后点开链接 装压+dp!!!!哦!!!!!!巧妙!!!! 就先把目标状态还有各个优惠的状态处理好 然后就是一个完全背包处理用优惠 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int S=100+5,N=10,P=10000+5,C=1000+5; 4 int sale[S

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

洛谷P2732 商店购物 Shopping Offers

P2732 商店购物 Shopping Offers 23通过 41提交 题目提供者该用户不存在 标签USACO 难度提高+/省选- 提交  讨论  题解 最新讨论 暂时没有讨论 题目背景 在商店中,每一种商品都有一个价格(用整数表示).例如,一朵花的价格是 2 zorkmids (z),而一个花瓶的价格是 5z .为了吸引更多的顾客,商店举行了促销活动. 题目描述 促销活动把一个或多个商品组合起来降价销售,例如: 三朵花的价格是 5z 而不是 6z, 两个花瓶和一朵花的价格是 10z 而不是

USACO 3.3 Shopping Offers

Shopping OffersIOI'95 In a certain shop, each kind of product has an integer price. For example, the price of a flower is 2 zorkmids (z) and the price of a vase is 5z. In order to attract more customers, the shop introduces some special offers. A spe