HDU 1170 Shopping Offers 离散+状态压缩+完全背包

题目链接:

http://poj.org/problem?id=1170

Shopping Offers

Time Limit: 1000MS
Memory Limit: 10000K
#### 问题描述 > 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.

输入

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.

输出

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

样例输入

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

样例输出

14

题意

告诉你每类产品的单价,和打算购买的数量。现在有些优惠活动,买一些特定数量的商品组合能够优惠,问你如何用最少的钱买到需要购买的商品。

题解

dp[i][j][k][l][m]代表购买了i个商品0...m个商品4,需要花的最少的money,然后每个优惠活动和单价都可以看作转移边。前面那个状态可以用六进制压缩下状态。

这样转化成了一个完全背包的额问题了。

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<sstream>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=7800;

struct In {
    int id,c,v;
    bool operator < (const In& tmp) const {
        return id<tmp.id;
    }
} in[11];

int dp[maxn],a[11],b[11],xp[11];

int main() {
    xp[0]=1; for(int i=1;i<11;i++) xp[i]=xp[i-1]*6;
    int n,m;
    while(scf("%d",&n)==1) {
        VI ha;
        VPII arr;
        for(int i=0; i<n; i++) {
            scf("%d%d%d",&in[i].id,&in[i].c,&in[i].v);
            ha.pb(in[i].id);
        }

        sort(all(ha));
        sort(in,in+n);

        int last=0;
        for(int i=0;i<n;i++){
            last+=xp[i]*in[i].c;
            arr.pb(mkp(xp[i],in[i].v));
        }

        scf("%d",&m);
        for(int i=0;i<m;i++){
            int cnt; scf("%d",&cnt);
            int stat=0;
            while(cnt--){
                int id,c;
                scf("%d%d",&id,&c);
                int p=lower_bound(all(ha),id)-ha.begin();
                stat+=c*xp[p];
            }
            int v; scf("%d",&v);
            arr.pb(mkp(stat,v));
        }

        clr(dp,-1);
        dp[0]=0;
        for(int i=1;i<=last;i++){
            for(int j=0;j<arr.sz();j++){
                int stat=arr[j].X,v=arr[j].Y;
                if(i-stat>=0&&dp[i-stat]>=0){
                    if(dp[i]==-1) dp[i]=dp[i-stat]+v;
                    else dp[i]=min(dp[i],dp[i-stat]+v);
                }
            }
        }

        prf("%d\n",dp[last]);

    }
    return 0;
}

//end-----------------------------------------------------------------------
posted @ 2016-09-29 23:02  fenicnn  阅读(223)  评论(0编辑  收藏  举报