牛客寒假算法基础集训营2题解(F题)

拿物品

https://ac.nowcoder.com/acm/contest/3003/F

图片说明
相信大家都看了出题人的题解了。首先,我们在这里要理解到两人都希望把得分尽量比对方大这句话的含义。假如我们是其中一方,我们要尽量与对方拉开差距,那么我们如何实现呢?就相当于考试,我们想要比他人排名更高的话,我们就要考得更高,亦或是对手要考的更低。在这个场景中,假如我们是牛牛,那么我就要尽量拿走当前物品A属性最高的,最好就同时把物品的B属性最高的拿走,当然,这种情况过于特殊化了,那么就普通的吧。其实,拿分最高的物品可以从A,B两者考虑,我可以只拿当前物品A的属性最高的,也可以只拿物品B的属性当前最高的。拿物品A属性高的大家很好理解,但是对于物品的B属性,拿走B属性更高的其实也是在压低对方的得分。也就是自己与对方的差距拉得更大了,这就是最优策略。所以,我们要同时考虑物品的A,B属性,也就得到了要拿当前物品A,B属性总和最高的。(我不知道这样解释你们可不可以理解,但希望可以静下心来仔细想想是不是这样的道理)出题人给出了具体的公式,我这也算是在强行解释了。下面是出题人的解释:
图片说明
到了这里,我们的目的就很明确了。我们把每个物品的a,b属性的和计算出来,在进行排序,然后按从大到小的顺序依次拿,但这里就有一个问题了,排过序的同学都知道,排序之后,数组的下标也会跟着改变,因为在这里下标是与地址相关联的,排序会改变原地址,原下标也随之改变。那么,我们有什么办法让下标与地址不相关联吗?或是排序时可以让下标与其一起改变呢?这里,我们介绍一个方法,就是对结构体进行排序。我们把相加的和用一个数表示,并且用另一个数记录其下标。对结构体排序只会按其某一个成员进行排序,不会改变其他成员的值。这就是我们想要的。

struct node{
    ll c;
    ll ans;
}res[N];

这里,我们把每个物体的a,b分数相加之和用c记录,把下标用ans进行记录。

bool cmp(node n1,node n2){
    return n1.c>n2.c;
}

这个函数是我们等下要用的sort函数(包含在algorithm里面的库函数)的时候要用到的参数,因为sort函数默认是从小到大排序,我们要改为从大到小排序就要把这个当成参数加入其中(不懂得建议先去自行百度sort函数),其实要默认也可以,只是后面处理更加复杂一点。这里我们方便理解就用这个当作参数吧。注意,我们在这个函数里规定以结构体里的c的大小进行排序(从大到小)。如果把小于号反过来就是从小到大,当然,没必要,因为这是默认的。

sort(res+1,res+1+n,cmp);

这个就是排序函数,但是我们这里是对结构体的某一个成员进行排序。在cmp函数里已经规定好了用c的大小。
接下来,就是总的代码

//万能头文件 
#include<bits/stdc++.h>
using namespace std;
const int N=200020;
typedef long long ll;
struct node{
    ll c;
    ll ans;
}res[N];
bool cmp(node n1,node n2){
    //以结构体c的大小按从大到小排序 
    return n1.c>n2.c;
}
ll a[N],b[N];
int main(){
    int n;
    cin>>n;
//因为物品计数是从1开始的,所以建议从1开始枚举,之后好记录下标,也就是该物品是第几件物品
    for(int i=1;i<=n;i++){
        cin>>a[i];
        res[i].c=a[i];   //把当前物品A属性赋给当前结构体的成员c 
        res[i].ans=i;  //在这里同时记录好下标存入结构体的ans成员,所以输入b的数据时就不必再这步了 
    }
    for(int i=1;i<=n;i++){
        cin>>b[i];
        res[i].c+=b[i];   //当前结构体的c加上B属性 
    }
    //到了这里我们已经收集好了每件物品的A,B属性之和,也记下了相应的下标存入res数组的元素里(也就是结构体) 
    sort(res+1,res+1+n,cmp);
    //在排好序后,我们的每个结构体中的c是按大小排的,而且它最初的下标也还记着 
    for(int i=1;i<=n;i++){
        //牛牛先拿,所以就是拿到奇数输出当前结构体的ans成员,也就是原下标 
        if(i%2==1)  cout<<res[i].ans<<" ";
    }
    cout<<endl;
    for(int i=2;i<=n;i++){
        //牛可乐拿到偶数,遇到偶数就输出当前结构体中的ans成员
        if(i%2==0)  cout<<res[i].ans<<" ";
    }
    return 0;
}

总体思路就是这样,有疑问下方留言。

牛客寒假算法基础训练营2题解C题https://blog.nowcoder.net/n/9d821b9b4f2445749680a2777d4746cd

全部评论
写的太好了,感谢感谢
点赞 回复 分享
发布于 2020-02-16 00:13

相关推荐

秋招结束已经一段时间了&nbsp;一直在忙着毕业的事情&nbsp;浅浅总结一下自己的秋招经历吧~本人BG双非硕&nbsp;后端选手&nbsp;有一段小厂+腾讯暑期实习腾讯暑期转正loser秋招结束已经结束了有一段时间了总结一下秋招历程最大的感受就是秋招比起暑期更加卡学历秋招总共投了60多家吧一直面&nbsp;一直挂也投了两家银行科技岗&nbsp;都走到终面体检了都拒了(总体感觉本地的银行还是挺容易过的)可能本人更想去私企&nbsp;并且银行也挺卷听说一直到11月就只有一家小厂的offer并签约当保底然后也突然被WXG捞了&nbsp;本来都不对腾讯抱有希望了可能经过一整个秋招的面试积累吧&nbsp;以及本人有ACM经历&nbsp;WXG整体面试以做题偏多(一二面做了5道题&nbsp;4道hard)&nbsp;比较合自己胃口&nbsp;差不多半个月就把五轮面试过了进入录用评估&nbsp;但也一直没有结果到后面也陆陆续续有几家中厂也终面过泡池子一直到12月初华子给开了base杭州&nbsp;14a因为华子公积金的原因&nbsp;和小厂薪资上差距不大&nbsp;所以也一直犹豫是否毁约签华子&nbsp;但是内心也还对WXG抱有一丝幻想(虽然一直没有保温也没有任何消息)然后一直到12月中下旬&nbsp;华子要求去现场签约了&nbsp;但是WXG还是没有消息&nbsp;然后就连续发邮件和打电话催了好多次&nbsp;还是回复耐心等待直到华子签约那天&nbsp;经过内心挣扎已经决定毁约签华子了&nbsp;可能还是想平台更大一点吧&nbsp;然后最戏剧性的一幕来了&nbsp;就在我发毁约邮件没有5秒&nbsp;WXG打电话开奖了&nbsp;并且开奖也十分有诚意&nbsp;最终还是没有签约成功华子&nbsp;研究生期间也打了很多次华子的比赛还是对华子有感情的555整个秋招都是伴随着焦虑的&nbsp;我认为自己也是秋招大部分人的画像&nbsp;屡屡碰壁后不断怀疑自己&nbsp;但是可能自己也比较幸运吧&nbsp;但是也感谢自己在一次次陷入迷茫都没有放弃自己&nbsp;还是一直努力背八股&nbsp;刷题也祝各位牛友们共勉&nbsp;就算暂时没有好的offer&nbsp;不放弃一定会有好的结果的!!
点赞 评论 收藏
分享
评论
6
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务