状压 + 背包

Description

In a shop each kind of product has a price. For example, the price of a
flower is 2 ICU (Informatics Currency Units) and the price of a vase is 5
ICU. In order to attract more customers, the shop introduces some
special offers.

A special offer consists of one or more product items for a reduced
price. Examples: three flowers for 5 ICU instead of 6, or two vases
together with one flower for 10 ICU instead of 12.

Write a program that calculates the price a customer has to pay for
certain items, making optimal use of the special offers. That is, the
price should be as low as possible. You are not allowed to add items,
even if that would lower the price.

For the prices and offers given above, the (lowest) price for three
flowers and two vases is 14 ICU: two vases and one flower for the
reduced price of 10 ICU and two flowers for the regular price of 4 ICU.

Input

Your program is to read
from standard input. The first line contains the number b of different
kinds of products in the basket (0 <= b <= 5). Each of the next b
lines contains three values c, k, and p. The value c is the (unique)
product code (1 <= c <= 999). The value k indicates how many
items of this product are in the basket (1 <= k <= 5). The value p
is the regular price per item (1 <= p <= 999). Notice that all
together at most 5*5=25 items can be in the basket. The b+2nd line
contains the number s of special offers (0 <= s <= 99). Each of
the next s lines describes one offer by giving its structure and its
reduced price. The first number n on such a line is the number of
different kinds of products that are part of the offer (1
<= n <= 5). The next n pairs of numbers (c,k) indicate that k
items (1 <= k <= 5) with product code c (1 <= c <= 999) are
involved in the offer. The last number p on the line stands for the
reduced price (1 <= p <= 9999). The reduced price of an offer is
less
than the sum of the regular prices.

Output

Your program is to write to standard output. Output one line with the lowest possible price to be paid.

Sample Input

2
7 3 2
8 2 5
2
1 7 3 5
2 7 1 8 2 10

Sample Output

14

题意:超市里面有一些商品,商品有任意多个,再给你这个人的购物清单,并且在超市里会不定期有一些打折促销的活动,购买一些指定组合的商品会有优惠折扣,但是要求这个人所购买的全部商品数量必须恰好是指定的。思路分析:因为商品只有 5 种,比较好想到的就是整一个 5维的 dp背包,想一想还有没有更优的方案,最多有5种商品,并且每种商品最多有5个,那么不就可以压缩为5位6进制的数了吗,表示此时的状态。然后转变为一个完全背包。代码示例:
int n, m;
map<int, int>mp;
struct node
{
    int s; // 状态
    int cost; // 花费
}pre[120];
int dp[10000];

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int a, b, c;
    int state=0;
    int k = 1;

    cin >> n;
    for(int i = 1; i <= n; i++){
        scanf("%d%d%d", &a, &b, &c);
        mp[a] = i-1;
        state += b*pow(6, i-1);
        pre[k].s = pow(6, i-1);
        pre[k++].cost = c;
    }
    //printf("%d\n", state);

    cin >> m;
    int id, cnt;
    for(int i = 1; i <= m; i++){
        scanf("%d", &a);
        int sum = 0;
        for(int j = 1; j <= a; j++){
            scanf("%d%d", &id, &cnt);
            sum += pow(6, mp[id])*cnt;
        }
        scanf("%d", &c);
        pre[k].s = sum;
        pre[k++].cost = c;
    }

    memset(dp, inf, sizeof(dp));
    dp[0] = 0;
    for(int i = 1; i < k; i++){
        for(int j = pre[i].s; j <= state; j++){
            dp[j] = min(dp[j], dp[j-pre[i].s]+pre[i].cost);
        }
    }
    printf("%d\n", dp[state]);
    return 0;
}

原文地址:https://www.cnblogs.com/ccut-ry/p/9133027.html

时间: 2024-08-30 07:43:36

状压 + 背包的相关文章

POJ 2923 Relocation(状压+背包)

Relocation Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2340   Accepted: 965 Description Emma and Eric are moving to their new house they bought after returning from their honeymoon. Fortunately, they have a few friends helping them r

POJ2923--Relocation(01背包+状压dp)

果然对状压DP,我根本就不懂=.= /************************************************** Problem: 2923 User: G_lory Memory: 720K Time: 157MS Language: G++ Result: Accepted **************************************************/ #include <iostream> #include <cstring>

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

POJ 2923 【01背包+状态压缩/状压DP】

题目链接 Emma and Eric are moving to their new house they bought after returning from their honeymoon. Fortunately, they have a few friends helping them relocate. To move the furniture, they only have two compact cars, which complicates everything a bit.

UVA - 10817 Headmaster&#39;s Headache (状压类背包dp+三进制编码)

题目链接 题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教.在职教师必须选. 可以把“每个课程已经分别有几个人教”作为状态来进行转移,每个人能教的课程集合作为“物品重量”,工资作为“价值”来更新dp值,类似01背包,每放进一个人,从后往前更新即可. 状态的表示可以用三进制编码,为了写起来舒服,我写了个结构体作为状态和编码转换的桥梁,也可以进行状态的“加法运算”,虽然速度比较慢就是了~~ 有

HDU 6149 Valley Numer II(状压DP)

题目链接 HDU6149 百度之星复赛的题目……比赛的时候并没有做出来. 由于低点只有15个,所以我们可以考虑状压DP. 利用01背包的思想,依次考虑每个低点,然后枚举每个状态. 在每个状态里面任意枚举不在这个状态中的两个点,如果能构成一个valley,那么更新答案. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i,

【UVa】Headmaster&#39;s Headache(状压dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758 晕....状压没考虑循环方向然后错了好久.. 这点要注意...(其实就是01背包变成了完全背包QAQ 我们将课程拆成两个点,然后状压 那么答案就是(1<<(s<<1))-1 转移就不说了,,,,,太简单.. #include <cstdio> #in

ZOJ3802 Easy 2048 Again (状压DP)

ZOJ Monthly, August 2014 E题 ZOJ月赛 2014年8月 E题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5334 Easy 2048 Again Time Limit: 2 Seconds      Memory Limit: 65536 KB Dark_sun knows that on a single-track road (which means once he passed this

HDOJ 4906 Our happy ending 状压DP(数位DP?)

http://acm.hdu.edu.cn/showproblem.php?pid=4906 题意: N个数的序列,每个数可以选择填0-L,如果一个序列可以选出某些数,他们的和为K,那么这个序列就是”好序列“,给定N<=20,K<=20,0<=L<=10^9,问好序列的个数. 分析: N和K很小,所以要想办法利用这个特性(状压?搜索?).虽然L很大,但实际上一个数大于K的时候,肯定是不能选他组成K的.我们就先考虑L<=K的做法. 然后还是考虑不出来.. 好吧,看题解吧.. 目