• HDU4268 2012ACM长春赛区网络赛 Alice and Bob


    题目:HDU4268(贪心)

    题意是Alice和Bob都有N张卡片,卡片各有尺寸,Alice拿自己的卡片分别去盖Bob的,给出每张卡片的尺寸,问最多可以盖住多少张。

    先说一下我错误的解题方法,主要思想就是拿最大的去盖最大的。分别对Alice和Bob的卡片在两个set中进行排序(排序是自动的),

    按卡片的h降序排,h相同时按w的降序排。然后以Bob的set做循环,取Alice的set首端的卡片去盖,能盖住则删去,代码如下:

    #include <iostream>
    //#include <fstream>
    #include <set>
    #define FOR(a,b) for(int i = (a);i < (b);i ++)
    using namespace std;
    
    class Card
    {
    public:
        int h,w;
        bool operator<(const Card& c) const //插入set时自动排序,要自定义"<"操作符
        {
            if( h == c.h) return w < c.w;
            return h < c.h;
        }
        bool CanCover(const Card& c) const
        {
            return (h >= c.h && w >= c.w);
        }    
    };
    
    int main()
    {
        //ifstream cin("in.txt");
        multiset<Card> Alice,Bob;
        multiset<Card>::iterator ap,bp;
        Card c;
        int t,n,ans;
        cin>>t;
        while (t --)
        {
            Alice.clear();
            Bob.clear();
            ans = 0;
    
            cin>>n;
            FOR(0,n)
            {
                cin>>c.h>>c.w;
                Alice.insert(c);
            }
            FOR(0,n)
            {
                cin>>c.h>>c.w;
                Bob.insert(c);
            }
    
            ap = Alice.begin();
            while (ap != Alice.end())
            {
                bp = Bob.begin();
                if(ap->CanCover(*bp))
                {
                    Bob.erase(bp);
                    ans ++;
                }
                ap ++;
            }
            cout<<ans<<endl;
        }
    }

    我拿着这个代码提交了好几次都不对,然后就去参考了牛人的博客,看了半天才发现自己陷入了思维定势,正确思维应该是,对于Bob的每张卡片,把Alice的满足高度大于这张卡片的所有卡片组成一个集合(set),从集合中找w最接近的卡片,找到则从集合中删去。

    正确的代码如下:

    #include <iostream>
    //#include <fstream>
    #include <set>
    #include <algorithm>
    #define FOR(a,b) for(int i = (a); i < (b); i ++)
    using namespace std;
    const int maxnum = 100005;
    
    struct Card
    {
        int h,w;
        bool operator<(Card& c)
        {
            return (h < c.h);
        }
    };
    
    Card Alice[maxnum],Bob[maxnum];
    
    int main()
    {
        //ifstream cin("in.txt");
        multiset<int> mi;
        multiset<int>::iterator mit;
        int t,n,ans;
        cin>>t;
        while (t --)
        {
            cin>>n;
    
            memset(Alice,0,sizeof(Card)*n);
            memset(Bob,0,sizeof(Card)*n);
            mi.clear();
            ans = 0;
    
            FOR(0,n)
            {
                cin>>Alice[i].h>>Alice[i].w;
            }
            FOR(0,n)
            {
                cin>>Bob[i].h>>Bob[i].w;
            }
    
            sort(Alice,Alice+n);
            sort(Bob,Bob+n);
    
            int p = 0;
            FOR(0,n)
            {            
                while (p < n && Bob[p].h <= Alice[i].h)
                {
                    mi.insert(Bob[p].w);
                    p ++;
                }
                if(mi.size())
                {
                    mit = mi.lower_bound(Alice[i].w);
                    if(mit == mi.end()) mit --;
                    if(mit != mi.begin() && Alice[i].w < *mit) mit --;
                    if(Alice[i].w >= *mit)
                    {
                        mi.erase(mit);
                        ans ++;
                    }
                }
            }
            cout<<ans<<endl;
        }
    }
    本博客所有博文,若无专门说明皆为原创,转载请注明作者和出处!
  • 相关阅读:
    STL中set底层实现方式? 为什么不用hash?
    main 主函数执行完毕后,是否可能会再执行一段代码?(转载)
    计算机网络(转载)
    2014! 的末尾有多少个0
    最常见的http错误
    内存分配(转载)
    delphi中指针操作符^的使用
    虚拟方法virtual的用法
    调用父类方法
    指针
  • 原文地址:https://www.cnblogs.com/ifinver/p/2706474.html
Copyright © 2020-2023  润新知