贪心技巧

贪心

贪心其实就是按照某种规则排序。

乱搞

如果不知道应该按照什么规则排序,可以将自己能想到的所有排序方式都排一遍,从其中取更优秀的答案,排序次数越多只能使答案更优秀,所以放心排。

拟阵

先找对于只有两个数据的情况进行手玩。找到其中的排序方式,然后对于后面的任意两个数排序时(不一定是连续的),排序方式与只有两组数据时是相同的。

例题

luogu1080

先考虑只有两个大臣,只有两种情况(假如用l,r表示国王的左右手,l1,r1表示一号大臣,l2,r2表示二号大臣):

如果1号大臣在前面,那么一号大臣得到的金币就是\(\frac{l}{r1}\),二号大臣得到的金币就是\(\frac{l*l1}{r2}\)最终答案就是其中的max

如果2号大臣在前面那么一号大臣的得到的金币就是\(\frac{l}{r2}\)二号大臣得到的金币就是\(\frac{l*l2}{r1}\),最终答案就是在其中取max

那么排序的时候就可以对于任意两个大臣按照这个进行比较,也就是假装其他大臣都不存在

bool cmp(node x,node y)
{
    int l=a[1].l;
    int k1=max(l/x.r,l*x.l/y.r);
    int k2=max(l/y.r,l*y.l/x.r);
    if(k1<=k2) return 1;
    return 0;
}

然后可以化简(仅仅为了好看)

在上面的基础上,我们可以看成比较谁哪种情况更大就让他更靠后,首先明显\(\frac{l}{r1}\)\(\frac{l}{r2}\)的存在是没有意义的,因为有明显另外两种比他们更大。

然后还剩下\(\frac{l*l1}{r2}\)\(\frac{l*l2}{r1}\)将l约去,然后将r1与r2分别乘过去,然后就成了比较l1r1与比较l2r2比较小的就是比较优秀的那个。

然后发现如果乱搞,按照l*r排序也是不难想到的。

因为这个题需要知道最终答案,所以要写个高精。

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
struct bignum
{
    int a[100000],n;
    bignum ()
    {
        n=0;
        memset(a,0,sizeof(a));
    }
    bignum (int x)
    {
        n=0;
        memset(a,0,sizeof(a));
        while(x)
        {
            a[++n]=x%10;
            x/=10;
        }
    }
    void print()
    {
        for(int i=n;i>=1;--i)
            printf("%d",a[i]);
        printf("\n");
    }
};
bignum operator * (const bignum &x,int y)
{
    bignum c=x;
    for(int i=1;i<=c.n;++i)
        c.a[i]*=y;
    for(int i=1;i<=c.n;++i)
    {
        if(c.a[i]>=10)
        {
            c.a[i+1]+=c.a[i]/10;
            c.a[i]%=10;
        }
        if(i==c.n&&c.a[i+1]!=0) c.n++;
    }   
    return c;
}
bignum operator / (const bignum &x,int y)
{
    bignum c;
    c.n=x.n;
    int n=c.n;
    int k=0,tmp=0;
    for(int i=n;i>=1;--i)
    {
        tmp=k*10+x.a[i];
        c.a[n--]=tmp/y;
        k=tmp%y;
    }
    while(c.a[c.n]==0&&c.n>0) c.n--;
    if(c.n==0) c.n++;
    return c;
}
bool operator < (const bignum &x,const bignum &y)
{
    if(x.n!=y.n) return x.n<y.n;
    for(int i=x.n;i>=1;--i)
        if(x.a[i]!=y.a[i]) return x.a[i]<y.a[i];
}
const int N=11000;
struct node
{
    int l;
    int r;
}e[N];
bool cmp(node x,node y)
{
    return x.l*x.r<y.l*y.r;
}/*
bool cmp(node x,node y)
{
    int l=e[1].l,r=e[1].r;
    int k1=max(l/x.r,l*x.l/y.r);
    int k2=max(l/y.r,l*y.l/x.r);
    if(k1<=k2) return 1;
    return 0;
}*/
int main()
{
    //freopen("2.in","r",stdin);
    int n;
    scanf("%d",&n);
    ++n;
    for(int i=1;i<=n;++i)
        scanf("%d%d",&e[i].l,&e[i].r);
    sort(e+2,e+n+1,cmp);
    bignum ans(e[1].l),anss(0);
    int ans2=e[1].l,anss2=0;
    for(int i=2;i<=n;++i)
    {

        anss=max(anss,ans/e[i].r);
        anss2=max(anss2,ans2/e[i].r);
        ans=ans*e[i].l;
        ans2=ans2*e[i].l;

    }
    //printf("%d",anss);
    anss.print();
    return 0;
}
全部评论

相关推荐

10-23 16:33
门头沟学院 Java
本人某中9本科,成绩中等,目前没科研没实习,目前后端学到了javaWeb,开始没定好方向,在学国外课程,走工程路线起步有点晚了,到这个时间点了还在学JavaWeb,顿感迷茫,不知道是坚持走下去还是寒假去准备考研。考研这个路弄得我还是心痒痒的,因为从众考研的人也不在少数,所以会有这方面的心理安慰吧,就是“不行我可以去考研啊”,而且意味着三年的缓冲,为了复试还有积攒经验美化简历,其实现在也可以去申入实验室打杂;就业可能意味着多些工作经验,工程岗应该到后面还是经验大于学历?还是有点迷茫了,求助好心人有无路线启发
千千倩倩:同27给点建议,现在这个时间点可以快速看完外卖和点评,不用跟着敲,但一定要在看的时候总结每个部分的整个业务流程,对其中的实现有一个大概的印象。然后直接开始看八股,刷算法。八股和算法最好还是在项目学习中穿插着看。如果计算机基础,算法这些基础好,加上每天刻苦学习,两周可以达到勉强能面试的水平,到时候就直接海投中小厂,在约面和面试的过程中不断巩固知识。没找到实习也没关系,就当积累经验。再沉淀一波直接明年三月开始投暑期,毕竟是9本,总是有面试机会的,只要你这三个月不懈怠,面试发挥得一定不错,只要拿到一个中,大厂暑期实习,秋招就有竞争力了。总得而言,现在还有机会,但是时间非常紧张,需要你结合自己情况考虑,共勉
你会选择考研还是直接就业
点赞 评论 收藏
分享
10-21 00:37
已编辑
山东大学 C++
小浪_Coding:你问别人,本来就是有求于人,别人肯定没有义务免费回答你丫, 有点流量每天私信可能都十几,几十条的,大家都有工作和自己的事情, 付费也是正常的, 就像你请别人搭把手, 总得给人家买瓶水喝吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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