【思维】UVa 11292 Dragon of Loowater

UVa 11292 Dragon of Loowater

这里写图片描述

题意

有n条龙,有m个勇者,每个勇者只能消灭能力值小于等于自身的龙,每个勇者消灭一条龙之后要付给等于他能力值的金钱,每个勇者有且只能雇佣一次,问怎样雇佣勇者才能消灭龙且花费最少,若不能消灭,则输出Loowater is doomed!

思路

我一开始的思路

对于每个条恶龙,将其从大到小排序,在勇者当中用二分搜索查找第一个大于等于条龙能力值的勇者,没有就直接结束,有的话记录这个勇者的花费,同时删除这条龙和这个勇者,再考虑下一条龙…知道所有龙考虑完或者没有勇者了。
最后如果龙的数量为0,就输出花费,不为就输出Loowater is doomed!。

思路评价

这种思路AC了,不过实现极其复杂,使用了优先队列去存龙,使用vector去存勇者。二分查找,vector的删除元素,总之就是各种xjb操作。
而且实现效率不高,代码编写要求难
这里写图片描述

AC代码1
#include<bits/stdc++.h>
using namespace std;

void solve(void)
{
    int n,m;
    while(scanf("%d%d",&n,&m))
    {
        priority_queue<int,vector<int>,greater<int> >a;
        vector<int>b;
        if(n==0&&m==0) break;
        for(int i = 0 ; i < n ; i++)
        {
            int temp;
            cin>>temp;
            a.push(temp);
        }
        for(int j = 0 ; j < m ; j++)
        {
            int temp;
            cin>>temp;
            b.push_back(temp);
        }
        sort(b.begin(),b.end());
        int ans = 0;
        int flag = 0;
        while(!b.empty())
        {
            int aim = a.top();
            a.pop();
            auto now = lower_bound(b.begin(),b.end(),aim) - b.begin();
            //cout<<now<<endl;
            if(b[now]==*b.end()&&aim!=*b.end())
            {
                cout<<"Loowater is doomed!"<<endl;
                flag = 1;
                break;

            }
            else
            {
                vector<int>::iterator it = b.begin() + now;
                ans+=*it;
                b.erase(it);
            }
            if(a.empty()) break;
        }
        if(flag==0)
        {
            if(a.empty()) cout<<ans<<endl;
            else cout<<"Loowater is doomed!"<<endl;
        }

    }
}

int main(void)
{
    solve();
    return 0;
}

标程的思路

把龙和人的能力值分别存储,然后同时从小到大排序,从最小的开始比较,设定两个标志量i和j,i代表当前比较的龙的编号,j表示当前比较的人的标号。
如果人的能力值大于等于龙的能力值,i++,j++,记录花费。
否则,人的编号j++,移动到下一个人再去比较。
直到人的编号等于人数或者龙的编号等于龙数则退出。
如果最后龙的编号等于龙数则说明所有的龙都被消灭了,输出花费就可。
否则输出Loowater is doomed!

思路评价

简化了思维方式,从而简化了代码。
思路均是从对于每条恶龙,找到第一个比他能力值大的勇者。
但是这个是从头开始一个一个比对,能力小的勇者永久的被遗弃,效率更高。
这里写图片描述

AC代码
#include<bits/stdc++.h>
using namespace std;


#define maxn 20005

int a[maxn];
int b[maxn];

void solve(void)
{
    int n,m;
    while(scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        for(int i = 0 ; i < n ; i++) scanf("%d",&a[i]);
        for(int i = 0 ; i < m ; i++) scanf("%d",&b[i]);
        int i = 0,j = 0;
        sort(a,a+n);
        sort(b,b+m);
        long long sum = 0;
        for(i = 0 ; i < m ; i++)
        {
            if(b[i] >= a[j]) {sum+=b[i];j++;}
            if(j==n) break;

        }
        //cout<<j<<endl;
        if(j==n) printf("%lld\n",sum);
        else printf("Loowater is doomed!\n");
    }
}



int main(void)
{
    solve();
    return 0;
}


相比起来…..

没有必要使用二分查找,因为本身就可以从头开始线性查找,而且对于每条龙,没有打败他的勇者,那么能力值小于没有打败他的勇者就肯定也打败他,之前的比较可以继续使用,二分查找不但也需要排序,其实也浪费了一部分查询结果。
没必要使用优先队列,应为数组就足够实现。也并不需要自动排序,完全就是花里胡哨的写法。
Don’t trouble troubles till trouble troubles you!

所能学到的

由于这次的复杂思路,反而巩固了一波STL的知识点。

less 和 greater
less<int>()
greater<int>()

less和greater 都是是头文件xfunctional中定义的两个结构。

        // TEMPLATE STRUCT greater
template<class _Ty>
    struct greater
        : public binary_function<_Ty, _Ty, bool>
    {   // functor for operator>
    bool operator()(const _Ty& _Left, const _Ty& _Right) const
        {   // apply operator> to operands
        return (_Left > _Right);
        }
    };

        // TEMPLATE STRUCT less
template<class _Ty>
    struct less
        : public binary_function<_Ty, _Ty, bool>
    {   // functor for operator<
    bool operator()(const _Ty& _Left, const _Ty& _Right) const
        {   // apply operator< to operands
        return (_Left < _Right);
        }
    };

greater是从大到小排序的一种写法
less是从小到大排序的一种写法

vector当中的erase()

erase有两种用法:
iterator erase(iterator it):删除向量中迭代器指向元素
iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
删除一个元素,那么我们可以这样写:

vector<int>::iterator it = b.begin() + now;///找到这个元素的位置。
b.erase(it);///删除它。

猜你喜欢

转载自blog.csdn.net/peng0614/article/details/80976869