依然是DP,题目大意:给出若干物品与单价,然后给出一系列物品组合后优惠价,问把所有物品买下来最少需要多少钱。
状态压缩,物品最多5种,然后每种最多5个,用6进制数储存,每种数量在不同时的最优解,第一次盲打状态压缩DP,自然是无限WA···幸亏还是过了。代码依然很蠢,又长又臭。
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<cstring>
#include<map>
using namespace std;
#define N 60000
struct st
{
int n;
int v;
}s[10];
struct mark
{
int num;
int v;
}ss[200];
int dp[N],six[10],ch[10],add[10];
int n,m,sum,mm;
map<int,int>maps;
void deal()
{
six[0]=1;
for(int i=1;i<8;i++)
{
six[i]=six[i-1]*6;
}
}
void change(int i)
{
int j=0;
ch[0]=i%6;
while(i/6)
{
j++;
i/=6;
ch[j]=i%6;
}
}
bool judge(int i)
{
int j=0,k;
add[0]=i%6;
while(i/6)
{
j++;
i/=6;
add[j]=i%6;
}
for(j=0;j<n;j++)
{
if(ch[j]+add[j]>s[j].n)
return false;
}
return true;
}
void cut()
{
int i,j,k;
for(i=0;i<=sum;i++)
{
memset(ch,0,sizeof(ch));
change(i);
for(j=0;j<n;j++)
{
dp[i]+=s[j].v*ch[j];
// cout<<ch[j]<<' ';
}
// cout<<endl;
}
for(i=0;i<sum;i++)
{
memset(ch,0,sizeof(ch));
change(i);
for(j=0;j<mm;j++)
{
memset(add,0,sizeof(add));
if(judge(ss[j].num))
{
dp[i+ss[j].num]=min(dp[i+ss[j].num],dp[i]+ss[j].v);
}
}
}
}
int main()
{
int i,j,k,l;
deal();
while(cin>>n)
{
maps.clear();
memset(dp,0,sizeof(dp));
for( i=sum=0;i<n;i++)
{
cin>>j>>k>>l;
maps.insert(pair<int,int>(j,i));
s[i].n=k;
s[i].v=l;
sum+=six[i]*k;
}
cin>>m;
mm=0;
for(i=0;i<m;i++)
{
cin>>j;
for(k=1,l=0;k<=j;k++)
{
int id,num;
scanf("%d%d",&id,&num);
if(maps.find(id)==maps.end()||l==-1)
{
l=-1;
}
else
{
l+=six[maps.find(id)->second]*num;
}
}
int v;
scanf("%d",&v);
if(l!=-1)
{
ss[mm].num=l;
ss[mm++].v=v;
}
}
cut();
cout<<dp[sum]<<endl;
}
return 0;
}