算法之贪心书架

来源:互联网 发布:海信淘宝旗舰店 编辑:程序博客网 时间:2024/05/18 02:39

一、算法分析

    分析:这是一道贪心题,其实贪心的条件很明显:显然,塔中的奶牛数目越多,整座塔就越不稳定,于是奶牛们希望在能够到书架顶的前提下,让塔中奶牛的数目尽量少。 那么我们就可以得到一个贪心条件:每次都选取当前奶牛序列中选取一个最高的奶牛,在“奶牛塔”上叠上这个奶牛,然后将这个奶牛删除,这样我们可以保证这样的结果是最优的。可以使用STL sort来实现每次选取最优值的。

设,答案中奶牛的期待高度为E

方法一:(线性选择,时间复杂度(n*E)):

这种方法是最暴力的,每次扫描一遍,找到最大的那个,对于这道题,很可能超时

方法二:(排序+选择)

由于奶牛不高,这道题可以快速排序,也可以采用基数排序,

时间复杂度分别为:O(n*logn+E)和O(n+E)

//虽然说,已经找到了O(n)的算法,但是这是因为牛比较矮,而且是整数,如果奶牛的身高是浮点数,排序再选择并不是最好的方法!

方法三(建立在堆数据结构上的优先队列)

大家都知道,将一个长度为n的无序的序列调整为堆,

在均摊条件下,时间复杂度是O(n)(这个留给读者思考)

在堆的优先队列建立起来之后,每次弹出一个最高的奶牛,时间复杂度:O(logn)

所以,弹出E个牛,最后的时间复杂度为:O(n+E*logn)

这已经是一个很有针对性而且很有效的方法了,不过别着急,还有更好的方法

*方法四(建立在二分选择上的方法)

这个方法的时间复杂度是O(n)与E无关

在这里,我们仅提示这个方法的思想,

首先,如果给出一个长度为n的序列,我们已经有算法(2分选择)来找到第k大的数

那么,这个应用稍微改变一下,就可以求解一个长度为n的序列里,找到最少几个较

大的元素可以使他们的和不小于sum。


二、参考代码一

#include <cstdio>

#include <algorithm>

using namespace std;

int cow[20005];

int main()

{

   int N,B,high=0;

   scanf("%d %d",&N,&B);

   for(int i=0;i<N;i++)scanf("%d",&cow[i]);

   sort(cow,cow+N,greater<int>());

   for(int i=0;i<N;i++){

     high+=cow[i];

     if(high>=B){

        printf("%d\n",i+1);

        break;

     }

   }

   return 0;

}

   三、参考代码二

       

#include "iostream"  

#include "iomanip"  

#include "algorithm"  

using namespace std;  

struct metal  

{  

    double w;  

    double v;  

    double price;  

}a[201];  

double comp(metal a1,metal a2)  

{  

    return a1.price>a2.price;  

}  

int main()  

{  

    int k;  

    cin>>k;  

    while(k--)  

    {  

        double result=0;  

        double w;  

        int s;  

        cin>>w>>s;  

        double tempW,tempV;  

        for(int i=0;i<s;i++)  

        {  

            cin>>tempW>>tempV;  

            a[i].w= tempW;  

            a[i].v= tempV;  

            a[i].price= tempV/tempW;  

        }  

        sort(a,a+s,comp);  

        for(int i=0;i<s;i++)  

        {  

            if(w>=a[i].w)  

            {  

                result+=a[i].v;  

                w-=a[i].w;  

            }else   //考虑w装下所有金属并有空余  

            {  

                result+=w*a[i].price;  

                break;  

            }  

        }  

        cout<<fixed<<setprecision(2)<<result<<endl;  

    }  

}  


原创粉丝点击