【loli的胡策】联校11.4(贪心)

本文解析了一道比赛算法题目,介绍了如何使用贪心算法求解最优解,并给出了具体实现代码。通过对人员和怪物的位置进行合理分配,实现了攻击距离的最大化。

T1:

这里写图片描述
这里写图片描述

题解:

考试的时候写了O(nmlog(ans))的做法得了80pts
80pts:
先二分答案,然后对于每个人可以打到的怪物连边跑二分图匹配
100pts:
人的数量肯定大于等于怪物的数量
s点把数轴划分成了两部分,每个部分内互相打击是最优的
如果一部分的人很多,我们就从另一部分调一点过来
调过来的肯定要离s近一点啊,这样对于哪边都比较优
那么怎么确定每个人打哪个呢?以s为中心排序!
位于同一部分的怪物和人,排名相同的互相打击
算是贪心吧

代码:

#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct ll{int w;};
struct rr{int w;};
priority_queue<ll>ql[2];
priority_queue<rr>qr[2];
bool operator <(const ll &a,const ll &b){return a.w<b.w;}//弹出来坐标最大的 
bool operator <(const rr &a,const rr &b){return a.w>b.w;}//弹出来坐标最小的 
int n,m,s;
int main()
{
    freopen("kill.in","r",stdin);
    freopen("kill.out","w",stdout);
    int i,p,ans=0;int cnt1=0,cnt2=0;
    scanf("%d%d%d",&n,&m,&s);
    for (i=1;i<=n;i++) 
    {
        scanf("%d",&p);
        if (p<=s) ql[0].push((ll){p}),cnt1++;
        else qr[0].push((rr){p}),cnt2++;
    }
    for (i=1;i<=m;i++) 
    {
        scanf("%d",&p);
        if (p<=s) ql[1].push((ll){p}),cnt1--;
        else qr[1].push((rr){p}),cnt2--;
    }

    while (cnt1>0)//人多了 
    {
        rr t=qr[1].top(); qr[1].pop();
        cnt1--;
        ql[1].push((ll){t.w});
    }
    while (cnt2>0)//人多了 
    {
        ll t=ql[1].top(); ql[1].pop();
        cnt2--;
        qr[1].push((rr){t.w});
    }

    while (!ql[0].empty())
    {
        ll t1=ql[0].top(),t2=ql[1].top();
        ans=max(ans,abs(t1.w-t2.w)+abs(t2.w-s));
        ql[0].pop(); ql[1].pop();
    }
    while (!qr[0].empty())
    {
        rr t1=qr[0].top(),t2=qr[1].top();
        ans=max(ans,abs(t1.w-t2.w)+abs(t2.w-s));
        qr[0].pop(); qr[1].pop();
    }
    printf("%d",ans);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值