Gym 100231D Balloons 贪心

题意很好理解,一场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;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值