• HDU4415 Assassin’s Creed


    题目大意:有n个人,每个人有x,y两个值。x代表干掉他得到的分数,分数和不超过m;y代表干掉他后你能额外干掉多少个,且不计入总分。

    求干掉人数最多为多少,以及最小的分。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    考试最后40分钟想出正解贪心,思路太乱没时间码导致20。

    直接说正解:优雅的贪心

    如果将y为0的放入a集,其余放入b集,那么正解只能有两种情况:

    1.只从a中拿。

    2.拿走全部的b,剩下将b从小到大排序后去掉最小,然后将b并入a中,再从a中拿。

    为什么是这样的?

    首先我们可以知道,只要拿走一个b,可以带出全部的b。

    这样的话可以想象将bi建成一棵树:

    b1->b2->b3

      

           >b4->b5

           

                >b6

    假设它是一棵树

    假设干掉b2要100块钱,还有一个a2要200块钱。

    这样我们可以先干掉b2,花100,然后b1就少了一个儿子,在把a2放进去,就是:

    b2->b3

    b1->a2

       

       >b4->b5

           

        >b6

    这样就是花100块钱干掉a2了。

    我们还发现,b1是不能被置换的,因为它没有父亲。

    所以正解:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define ll long long
    int T,n,ac,bc;
    ll ax[N],bx[N],by[N],m;
    bool cmp(ll x,ll y)
    {
        return x<y;
    }
    int cs;
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            cs++;
            printf("Case %d: ",cs);
            scanf("%d%I64d",&n,&m);
            ll sy = 1;
            ac=bc=0;
            for(int i=1;i<=n;i++)
            {
                bc++;
                scanf("%I64d%I64d",&bx[bc],&by[bc]);
                if(!by[bc])
                {
                    ax[++ac]=bx[bc];
                    bc--;
                    continue;
                }
                sy+=by[bc];
            }
            sort(ax+1,ax+1+ac,cmp);
            ll ans1 = 0;
            ll ans2 = 0;
            for(int i=1;i<=ac;i++)
            {
                if(ans2+ax[i]<=m)
                {
                    ans1++;
                    ans2+=ax[i];
                }else
                {
                    break;
                }
            }
            if(!bc)
            {
                printf("%I64d %I64d
    ",ans1,ans2);
                continue;
            }
            sort(bx+1,bx+1+bc,cmp);
            ll ans3 = sy;
            ll ans4 = bx[1];
            if(ans4>m)
            {
                printf("%I64d %I64d
    ",ans1,ans2);
                continue;
            }
            for(int i=2;i<=bc;i++)
            {
                ax[++ac] = bx[i];
            }
            sort(ax+1,ax+1+ac,cmp);
            for(int i=1;i<=ac;i++)
            {
                if(ans3>=n)
                {
                    ans3=n;
                    break;
                }
                if(ans4+ax[i]<=m)
                {
                    ans3++;
                    ans4+=ax[i];
                }
            }
            if(ans1>ans3||(ans1==ans3&&ans2<ans4))printf("%I64d %I64d
    ",ans1,ans2);
            else printf("%I64d %I64d
    ",ans3,ans4);
        }
        return 0;
    }
  • 相关阅读:
    video和audio
    表单
    二叉树的先序遍历,后序遍历究竟是如何与快速排序,归并排序扯上关系?
    Python3下约瑟夫环的不同实现方式
    Golang下基于uint32的BitMap类库
    annotation
    流媒体技术
    C++系列之new 和 delete 的使用
    简易科学计算器的设计
    学生成绩档案管理系统的设计
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9749320.html
Copyright © 2020-2023  润新知