hdu1058 优先队列与map判重、 补充手动堆排序做法、

#include <iostream>
#include <queue>
#include <map>
#include <cstring>
using namespace std;
priority_queue<long long,vector<long long>,greater<long long> >q;//优先队列,值小的元素优先
map<long long,bool> mark;//map判重
int main()
{
    string sign;
    long long js=1,re[5843],fx[4]={2,3,5,7};//re 存储结果
    re[1]=1;
    for(int i=0;i<4;i++)
    q.push(fx[i]);
    for(;js<=5842;)
    {
        long long t=q.top();
        q.pop();
        re[++js]=t;
        for(int i=0;i<4;i++)
        {
            long long tmp=t*fx[i];
            if(!mark[tmp])
            {
                mark[tmp]=true;//修改重复标记
                q.push(tmp);
            }
        }
    }
    int n;
    while(cin>>n)
    {
        if(n==0) break;
        if(n%10==1&&n%100!=11)sign="st";
        else if(n%10==2&&n%100!=12)sign="nd";
        else if(n%10==3&&n%100!=13)sign="rd";
        else sign="th";
        cout<<"The "<<n<<sign<<" humble number is ";
        cout<<re[n]<<"."<<endl;
    }
}


下面是堆排序的做法:

#include <iostream>
#include <map>
#include <string>
using namespace std;
long long heap[90000];//建数组保存堆元素
int hlength;//保存堆的元素个数
void down(int p)
{
       //向下调整算法,p代表当前节点,q代表子节点
       int q=p*2;
       long long a=heap[p];//保存当前节点的值
       while (q<=hlength)
       {
              if (q<hlength&&heap[q]>heap[q+1])
              //选择两个子节点中的一个最小的
                        q++;
              if(heap[q]>=a) break;//如果子节点比当前节点大,就结束
              else//否则就交换
              {
                     heap[p]=heap[q];
                     p=q;
                     q=p*2;
              }
       }
       heap[p]=a;//安排原来的节点
}
void up(int p)
{
       //向上调整算法,p代表当前节点,而q代表父母节点
       int q=p/2;//获取当前节点的父母节点
       long long a=heap[p];//保存当前节点的值
       while (q<=hlength&&a<heap[q])
       {
              //如果当前节点的值比父母节点的值小,就交换
              heap[p]=heap[q];
              p=q;
              q=p/2;
       }
       heap[p]=a;//最后安排原来的节点
}
void insert(long long a)
{
       heap[++hlength]=a;//先往堆里插入节点值
       up(hlength);//进行向上调整
}
long long getmin()
{
//删除最小元素算法
       long long r=heap[1];//取出最小的元素
       heap[1]=heap[hlength--];//然后把最后一个叶子节点赋给根节点
       down(1);//调用向下调整算法
       return r;
}
void build()
{
//建堆算法
       for(int i=hlength/2;i>0;i--)
                  down(i); //从最后一个非终端节点开始进行调整
}
int main()
{
    map<long long,bool> mark;
    string sign;
    hlength=4;
    long long re[5843];
    re[1]=1;
    int n,js=1;
    heap[1]=2;heap[2]=3;
    heap[3]=5;heap[4]=7;
    int fx[4]={2,3,5,7};
    while(js<5842)
    {
        long long tmp=getmin();
        re[++js]=tmp;
        for(int i=0;i<4;i++)
        {
            long long t=tmp*fx[i];
            if(!mark[t])
            {
                mark[t]=true;
                insert(t);
            }
        }
    }
    while(cin>>n)
    {
        if(n==0) break;
        if(n%10==1&&n%100!=11)sign="st";
        else if(n%10==2&&n%100!=12)sign="nd";
        else if(n%10==3&&n%100!=13)sign="rd";
        else sign="th";
        cout<<"The "<<n<<sign<<" humble number is ";
        cout<<re[n]<<"."<<endl;
    }
}


对于HDU4546问题,还可以使用优先队列(Priority Queue)来解决。以下是使用优先队列的解法思路: 1. 首先,将数组a进行排序,以便后续处理。 2. 创建一个优先队列(最小堆),用于存储组合之和的候选值。 3. 初始化优先队列,将初始情况(即前0个数的组合之和)加入队列。 4. 开始从1到n遍历数组a的元素,对于每个元素a[i],将当前队列中的所有候选值取出,分别加上a[i],然后再将加和的结果作为新的候选值加入队列。 5. 重复步骤4直到遍历完所有元素。 6. 当队列的大小超过k时,将队列中的最小值弹出。 7. 最后,队列中的所有候选值之和即为前k小的组合之和。 以下是使用优先队列解决HDU4546问题的代码示例: ```cpp #include <iostream> #include <vector> #include <queue> #include <functional> using namespace std; int main() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.begin(), a.end()); // 对数组a进行排序 priority_queue<long long, vector<long long>, greater<long long>> pq; // 最小堆 pq.push(0); // 初始情况,前0个数的组合之和为0 for (int i = 0; i < n; i++) { long long num = pq.top(); // 取出当前队列中的最小值 pq.pop(); for (int j = i + 1; j <= n; j++) { pq.push(num + a[i]); // 将所有加和结果作为新的候选值加入队列 num += a[i]; } if (pq.size() > k) { pq.pop(); // 当队列大小超过k时,弹出最小值 } } long long sum = 0; while (!pq.empty()) { sum += pq.top(); // 求队列中所有候选值之和 pq.pop(); } cout << sum << endl; return 0; } ``` 使用优先队列的方法可以有效地找到前k小的组合之和,时间复杂度为O(nklog(k))。希望这个解法对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值