题目链接:http://hihocoder.com/contest/hihointerview22/problem/1
题意:
有m种财宝,第i种财宝有ai个,只能存放在与其相匹配的栈中,有n个插槽,每个插槽可以放一个栈,一共m种栈,每种栈有无限个。给出每个栈的最大大小(表示每个栈可以存放的数量)再给出每种财宝的单个价值。问可以获得的最大价值。
思想:是贪心吧,关键点就是注意不足一个栈的最大容量也可以存放在一个栈中,然后我开了一个优先队列维护可以获得的财宝的最大单价。然后直接贪心着做。
代码:
typedef long long ll;
struct ss{
ll c,v,s,sum;//c表示财宝的个数,v表示财宝的单个价值,s表示栈的最大容量,sum就是排序的关键,是我处理出来的一个值,表示一个栈中的最大价值。就等于是单价。
bool operator < (const ss &b)const
{
return sum<b.sum;
}//优先队列排序函数。
}e[10000+5];//结构体存输入的数据。
int main()
{
priority_queue<ss>q;
int n,s;
scanf("%d%d",&n,&s);//n表示n个插槽,s表示财宝种类数。
for(int i=1;i<=s;i++)
scanf("%lld",&e[i].c);
for(int i=1;i<=s;i++)
scanf("%lld",&e[i].v);
for(int i=1;i<=s;i++)
scanf("%lld",&e[i].s);
for(int i=1;i<=s;i++)
{
if(e[i].c>=e[i].s)
e[i].sum=e[i].s*e[i].v;
else
e[i].sum=e[i].c*e[i].v;
q.push(e[i]);
}
ll sum=0,num=0;//sum存总价值,num存已经填满的槽数。
while(!q.empty())//优先队列维护最大单价。保证取得一定是最合算的。
{
ss a=q.top();
q.pop();
if(a.c/a.s>0&&a.c/a.s+num<n)
{
num+=a.c/a.s,sum+=(a.c/a.s)*(a.v*a.s);
a.c-=(a.c/a.s)*a.s;
a.sum=a.c*a.v;
if(sum)//如果还剩余财宝,则入栈继续维护。
q.push(a);
}
else if(a.c/a.s+num>=n)//如果剩余的可以将插槽填满,则要处理好后退出循环。
{
num=n-num;
sum+=num*(a.v*a.s);
break;
}
else
{
num++;
sum+=a.c*a.v;
}
}
printf("%lld\n",sum);
}