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

商店买东西会有优惠政策,使用优惠政策使顾客花的钱尽可能的少。

这道题很有现实背景啊,起初看这道题想的是用规则去优化各种组合情况的物品,并没有想到用背包。因为没有做过“规则”这种物品

还有一点就是接收输入信息的时候若用高维数组很难控制,当时竟然写出了int (*it)[5][5][5][5] 这种东西。

这时,进制优化发挥作用了,其思想类似于康托展开,且因为这个问题并不是直接将位置映射到数集,而是各个不同物品的映射。六进制就够用了。将各个物品映射到一个六进制数字中的每一位,一位上的数字0-5表示物品个数。这样6^5-1=7776。一个数组就搞定。

注意物品组合是否满足时的判定。

PS: 貌似我的代码是见过的最短的也最好理解的。。。。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=10+1000;
int state[7777];//物品组合状态下的最小花费
int d[110],e[110];
struct P
{
    int num,val,cnt;
}p[maxn];
int hashnum[1100],N,M;//hash 物品编码
int check(int m,int n)//判断m是否满足这个优惠条件
{
    for(int i=0;i<5;i++,m/=6,n/=6)
        if(m%6<n%6) return 0;
    return 1;
}
int calc(int n)//计算这个状态原本的花费
{
    int res=0;
    for(int i=0;i<5;i++,n/=6)
    {
        res+=p[i].val*(n%6);
    }
    return res;
}int powr[]={1,6,36,216,1296,7776};
int main()
{
    while(~scanf("%d",&N))
    {
        int ansp=0;int sum=0;
        for(int i=0;i<N;i++)
        {
            scanf("%d%d%d",&p[i].num,&p[i].cnt,&p[i].val);
            hashnum[p[i].num]=i;
            ansp+=powr[i]*p[i].cnt;
            sum+=p[i].cnt*p[i].val;
        }
        memset(state,0,sizeof(state));
        state[ansp]=sum;
        scanf("%d",&M);
        int countall=0;int u,v, cnt;
        for(int i=0;i<M;i++)
        {
            int fin=0;
            scanf("%d",&cnt);
            for(int j=0;j<cnt;j++)
            {
                scanf("%d%d",&u,&v);
                u=hashnum[u];
                fin+=powr[u]*v;
            }
            scanf("%d",&u);
            d[i]=fin;e[i]=u;
        }
        for(int i=0;i<M;i++)
            for(int j=d[i], fin=d[i];j<=ansp;j++)
            {
                if(state[j]==0) state[j]=calc(j);
                if(check(j,fin))
                {
                    if(state[j-fin]==0 && j>fin) state[j-fin]=calc(j-fin);
                    if(state[j-fin]+e[i]<state[j]) state[j]=state[j-fin]+e[i];
                }
            }
        printf("%d\n",state[ansp]);
    }
    return 0;
}
时间: 2024-07-29 18:44:40

POj 1170 Shopping Offers(变形背包+进制优化) 100的相关文章

背包系列练习( 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 - 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 - 1170 Shopping Offers (五维DP)

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

POJ 1220 NUMBER BASE CONVERSION 高精度进制转换

      poj  50题拍照合影留念 NUMBER BASE CONVERSION Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4620   Accepted: 2115 Description Write a program to convert numbers in one base to numbers in a second base. There are 62 different digits: { 0-

POJ 1276 Cash Machine(多重背包的二进制优化)

题目网址:http://poj.org/problem?id=1276 思路: 很明显是多重背包,把总金额看作是背包的容量. 刚开始是想把单个金额当做一个物品,用三层循环来 转换成01背包来做.T了-- 后面学习了 用二进制来处理数据. 简单地介绍一下二进制优化:?(? ? ??)  假设数量是8,则可以把它看成是1,2,4,1的组合,即这4个数的组合包括了1-8的所有取值情况.这是为什么呢?将它们转换成二进制再观察一下: 1:1 2:10 4:100 1:1 二进制都只有0,1.所以1,2,4

HDU3605: Escape-二进制优化建图-最大流

目录 目录 思路: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 目录 题意:传送门 ?原题目描述在最下面. ?\(n(n\leq 100000)\)个人\(m(m\leq 10)\)个星球,每个星球容纳的人数有上限,每个人都有自己想去的星球意愿.问是否所有的都能去到外星球. 思路: ?肯定不能暴力建图,因为人太多了.注意到m的大小只有10.刷过状压dp的人应该都能想到要二进制优化. ?这是每个人其实都是没有区别的,有区别的只是他们的意愿.然后最多也只有\(2^{10} =1024\)

【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

进制进制进制~转换

从刚学计算机器就对进制转换有着莫名的反感,2进制 8进制 10进制 16进制各种转换. 下面就说下逻辑地址转换成物理地址的求法吧 首先,用户输入一个16进制的数字cin>>hex>>logic_add;   hex的意思是告诉计算机输入的数是以16进制方式输入的 这个时候你要是输出cout<<logic_add;  你会发现输出的是把这个16进制的数转换为10进制以后输出的结果 cout<<hext<<logic_add;这样输出的才是16进制.