POJ 1170 Shopping Offers

来源:互联网 发布:滨江淘宝摄影基地 编辑:程序博客网 时间:2024/06/03 17:38

题意:有n(n<=5)种物品,每种个数num<=5,价值1<=val<=999,现在商店推出m(m<=99)种促销方案,即若干种物品放在一起价格会比单个物品的总和便宜,问买到所有物品的最少花多少钱。


分析:六进制状态压缩DP,类似于完全背包。状态作为容量,价格作为价值。


Code:

#include <algorithm>#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <vector>#include <queue>#include <cmath>#include <map>#include <set>#define eps 1e-7#define LL long long#define pb push_back#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;const int inf=0x3f3f3f3f;const int base[6]={1,6,36,216,1296,7776};struct Offer{    int st,price;    Offer(){        st=price=0;    }};struct Item{    int cnt,p;};int n,m,state;int Hash[1000],dp[10000];Offer offer[105];Item item[5];bool check(int x,int y){    for(int i=0;i<n;i++){        if(x%6+y%6>item[i].cnt) return false;        x/=6; y/=6;    }    return true;}int calcu(int s){    int cost=0;    for(int i=0;s;i++){        cost+=(s%6)*item[i].p;        s/=6;    }    return cost;}int main(){    int code,cnt,p;    state=0;    scanf("%d",&n);    for(int i=0;i<n;i++){        scanf("%d %d %d",&code,&item[i].cnt,&item[i].p);        Hash[code]=i;        state+=base[i]*item[i].cnt;    }    scanf("%d",&m);    for(int i=0;i<m;i++){        scanf("%d",&p);        for(int j=0;j<p;j++){            scanf("%d %d",&code,&cnt);            offer[i].st+=base[Hash[code]]*cnt;        }        scanf("%d",&offer[i].price);    }    for(int i=1;i<=state;i++) dp[i]=inf;    dp[0]=0;    for(int i=0;i<m;i++){//以M种促销方案作为物品        for(int j=0;j<=state;j++){//以状态最为容量            if(dp[j]==inf) continue;            if(j+offer[i].st<=state&&check(j,offer[i].st)){                if(dp[j+offer[i].st]>dp[j]+offer[i].price) dp[j+offer[i].st]=dp[j]+offer[i].price;            }        }    }    int ans=inf,tmp;    for(int i=0;i<=state;i++){        tmp=calcu(state-i);        ans=Min(ans,dp[i]+tmp);    }    printf("%d\n",ans);    return 0;}


原创粉丝点击