UVA136 Ugly Numbers

链接:https://cn.vjudge.net/problem/UVA-136

        优先队列是一种抽象数据结构(Abstract Data Type, ADT),行为有些想队列,但先出队列的元素不是先进队列的元素,而是队列中优先级最高的元素,这样就可以允许类似于”急病病人插队“这样的事情发生。

        STL的优先队列也定义在头文件<queue>里,用”priority_queue<int> pq“来声明。这个pq是一个”越小的整数优先级越低的优先队列“。由于出对元素并不是最先进队的元素,出对的方法由queue的front()变为了top()。

        自定义类型也可以组成优先队列,但必须为每个元素定义一个优先级。这个优先级并不需要一个确定的数字,只需要能比较大小即可。看到这里,是不是想起了sort?没错,只要元素定义了”小于“运算符,就可以使用优先队列。在一些特殊的情况下,需要使用自定义方式比较优先级,例如,要实现一个“个位数大的整数优先级反而小”的优先队列,可以定义一个结构体cmp,重载“()”运算符,使其“看上去”像一个函数,然后用“priority_queue<int,vector<int>,cmp>pq”的方式定义。下面是这个cmp的定义:

struct cmp
{
    bool operator() (const int a,const int b) const//a的优先级比b小时返回true
    {
        return a%10>b%10;
    }
};

        对于一些常见的优先队列,STL提供了更为简单的定义方法,例如,“越小的整数优先级越大的优先队列”可以写成”priority_queue<int,vector<int>,greater<int>>pq“。注意,最后两个”>“符号不要写在一起,否则会被很多(但不是所有)编译器误以为是”>>“运算符。

        STL的queue头文件提供了优先队列,用”priority_queue<int> s“方式定义,用push()和pop()进行元素的入队和出队操作,top()取队首元素(但不删除)。

        本题的实现方法有很多,这里仅提供一种,即从小到大生成各个丑数。最小的丑数是1,而对于已生成的丑数,每次取出最小的丑数,生成3个新的丑数。唯一需要注意的是,同一个丑数有多种的生成方式,所以需要判断一个丑数是否已经生成过。

#include <iostream>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long LL;
const int coeff[3]={2,3,5};

int main()
{
    priority_queue<LL, vector<LL>, greater<LL> >pq;
    set<LL> s;
    pq.push(1);
    s.insert(1);
    for(int i=1;;i++)
    {
        LL x=pq.top();pq.pop();
        if(i==1500)
        {
            cout<<"The 1500'th ugly number is "<<x<<".\n";
            break;
        }
        for(int j=0;j<3;j++)
        {
            LL x2=x*coeff[j];
            if(!s.count(x2))
            {
                s.insert(x2);
                pq.push(x2);
            }
        }
    }
    return 0;
}
AC Code

        这里再写一种方法,不需要判断丑数是否已经生成,每次知生成最小的那个丑数,直到渣到1500个就可以。

#include <iostream>
#define maxn 100005
using namespace std;
int cmp(int a,int b,int c)
{
    if(a<b)
    {
        if(a<c)
            return a;
        else
            return c;
    }
    else
    {
        if(b<c)
            return b;
        else
            return c;
    }
    return c;
}
int ugly(int n)
{
    int a[maxn]={0,1};
    if(n<=1)
        return a[n];
    int cnt=2;
    while(1)
    {
        int c2=0,c3=0,c5=0;
        for(int i=1;i<cnt;i++)
        {
            if(a[i]*2>a[cnt-1])
            {
                c2=a[i]*2;
                break;
            }
        }
        for(int i=1;i<cnt;i++)
        {
            if(a[i]*3>a[cnt-1])
            {
                c3=a[i]*3;
                break;
            }
        }
        for(int i=1;i<cnt;i++)
        {
            if(a[i]*5>a[cnt-1])
            {
                c5=a[i]*5;
                break;
            }
        }
        a[cnt++]=cmp(c2,c3,c5);
        if(cnt>n)
            return a[n];
    }
}
int main()
{
    int n;
    cout<<"The 1500'th ugly number is "<<ugly(1500)<<".\n";
    return 0;
}
AC Code

 

posted @ 2018-08-31 20:33  子诚-  阅读(167)  评论(0编辑  收藏  举报