题意很好理解,一场acm比赛里,有两个房间A和B为通过题目的队伍供应气球,而赛场上不同的队伍距离A和B两房间的距离并不一样,且A和B房间都各有有限个气球。给出每个队伍需要的气球总数和初始时两房间各自拥有的气球 总数,请你安排分配方式,使运送气球的总路程最短(只计算单程)
先排序,再根据排好的顺序一个队一个队安排
排序比较有技巧,考虑到:A和B两房间是等地位的,对队伍排序时若将队伍到这两个房间的距离作为第一,第二关键字来排,会有不公平的情况,可能更倾向于A房间或B
因此,我们记一个队伍到A的距离为da,到B的距离为db,我们以da-db为关键字做升序排序,这样的好处是,排好序的序列里,越靠前的相对距离A越近,越靠后的相对距离B越近,注意我们要强调“相对”。
这样,我们从排好序的队列头开始分配,对于某一个队,如果A房间离他近且A的剩余气球足够这个队伍拿,那么A供给这个队所有需要的气球,若不够,从B拿。
若这个队离B更近,那么我们应该检查B房间剩下的气球能否充足供应给剩下的队伍,因为越往后的队伍,B分配给他就越有利(为此我们要维护一个变量leftballons来实时更新尚未分配的队伍所需的气球总数)
如果B房间的气球充足,那么在保证后续分配的前提下把多余的气球分配给当前队伍,如果无法满足当前队的需要,这个队的缺口由A房间补全,
code:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <vector>
#include <iomanip>
#include <cstring>
#include <queue>
#include <string>
#include <map>
#include <cstdlib>
#define LL long long
using namespace std;
const int mod=1e9+7;
const double pi=acos(-1);
int n;
int an,bn;
struct node
{
int x,ax,bx;
} q[1010];
int cmp(const void * p1,const void * p2)
{
const node* tp1=(node*)p1;
const node* tp2=(node*)p2;
int tmpa=(tp1->ax-tp1->bx);
int tmpb=(tp2->ax-tp2->bx);
if(tmpa==tmpb)return 0;
return (tmpa>tmpb)? +1:-1;
}
int main()
{
while(1)
{
cin>>n>>an>>bn;
if(n==0&&an==0&&bn==0)break;
int allnum=0;
int ans=0;
for(int i=0; i<n; i++)
{
scanf("%d%d%d",&q[i].x,&q[i].ax,&q[i].bx);
allnum+=q[i].x;
}
qsort(q,n,sizeof(node),cmp);
for(int i=0; i<n; i++)
{
int ta,tb;
ta=tb=0;
if((q[i].ax<q[i].bx)&&an>=q[i].x)
{
ta=q[i].x;
}
else if((q[i].ax<q[i].bx))
{
ta=an;
tb=q[i].x-ta;
}
else if(bn>=allnum)
{
tb=q[i].x;
}
else
{
int tmp=(bn-(allnum-q[i].x));
if(tmp<0)tmp=0;
tb=tmp;
ta=q[i].x-tb;
}
ans+=(q[i].ax*ta);
ans+=(q[i].bx*tb);
an-=ta;
bn-=tb;
allnum-=q[i].x;
}
cout<<ans<<endl;
}
}