题意:有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;
}

本文介绍了一种解决购物最优方案的问题,通过六进制状态压缩动态规划的方法,找到购买所有物品所需的最低价格。该方法类似于完全背包问题,将状态作为容量,价格作为价值。
1108

被折叠的 条评论
为什么被折叠?



