hrbust 1176 小陈老师、雪人【map+优先队列】

本文介绍了一个有趣的算法问题——如何最大化利用不同大小的雪球来堆砌雪人。通过使用优先队列和映射(map),文章提供了一种有效的解决方案,并详细解释了实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小陈老师、雪人
Time Limit: 1000 MSMemory Limit: 65536 K
Total Submit: 231(55 users)Total Accepted: 79(43 users)Rating: Special Judge: Yes
Description
东北的冬季,尤其是过年的时候,小陈老师喜欢去堆雪人。
每个雪人主要由三个雪球构成:大雪球、中雪球、小雪球。
他已经准备好了N个雪球,半径分别等于r1, r2, ..., rn。如果要堆一个雪人,就需要三个半径互不相等的雪球。
例如:
三个雪球的半径为1、2、3,能够用来堆一个雪人。但是半径为2、2、3或者2、2、2的三个雪球就不可以。
快帮帮小陈老师,算算他最多能用这些雪球堆多少个雪人。
Input
对于每组测试数据:
第1行,包含一个整数n(1≤n≤100000) — 雪球的数量。
第2行,包含n个整数 — 雪球的半径r1, r2, ..., rn (1≤ri≤1000000000)。
处理到文件结束
Output
对于每组测试数据:
第1行,输出最多能堆多少雪人 - k。
接下来k行,每行描述一个雪人,每行用空格分割三个数字分别表示大雪球、中雪球、小雪球的半径。
可以用任何顺序输出每个雪人。如果有多种可行解,输出任意一个即可。
Sample Input
7
1 2 3 4 5 6 7
3
2 2 3
Sample Output
2
3 2 1
6 5 4
0

数据比较大,用数组标记一个数出现的次数是不能够满足的,这里需要map,毕竟数据范围10^9、这里为什么要用到优先队列呢?一会再提 。

首先我们要处理数据,一切变量用int就行:

        priority_queue<node>s;
        int cont=0;
        map<int ,int >p;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            p[a[i]]++;
        }
        for(int i=0;i<n;i++)
        {
            if(p[a[i]]!=0)//不要重复添加进去数据~
            {
                tmp.date=a[i];
                tmp.ci=p[a[i]];
                s.push(tmp);
                p[a[i]]=0;
            }
        }
结构体中有这样两个数据:date,ci分别表示雪球的半径,和这个雪球还有多少个。这里我们举出这样的例子:

1(半径)有1个,2有4个,3有两个,4有三个、

明显最多能够凑出三组:

2 3 4、2 3 4、1 2 4、三组

但是假设我们这里用的优先是雪球数最小优先的话却只能做两组:

1 3 4、2 3 4、两组。

我们当然想要次数多的先用上,所以我们这里结构体优先队列用的是雪球剩下个数从多到少排列的、

最后上完整的代码:

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
using namespace std;
struct node
{
    int date;
    int ci;
    friend bool operator<(node a,node b)
    {
        return a.ci < b.ci;
    }
}tmp;
int a[1000005];
int ans[1000005][3];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        priority_queue<node>s;
        int cont=0;
        map<int ,int >p;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            p[a[i]]++;
        }
        for(int i=0;i<n;i++)
        {
            if(p[a[i]]!=0)
            {
                tmp.date=a[i];
                tmp.ci=p[a[i]];
                s.push(tmp);
                p[a[i]]=0;
            }
        }
        node b,c,d;
        int f[3];
        while(!s.empty())
        {
            b=s.top();
            s.pop();
            b.ci--;
            f[0]=b.date;
            if(s.empty())break;
            c=s.top();
            s.pop();
            c.ci--;
            f[1]=c.date;
            if(s.empty())break;
            d=s.top();
            s.pop();
            d.ci--;
            f[2]=d.date;
            sort(f,f+3);
            ans[cont][0]=f[0];
            ans[cont][1]=f[1];
            ans[cont][2]=f[2];
            if(b.ci>0)s.push(b);
            if(c.ci>0)s.push(c);
            if(d.ci>0)s.push(d);
            cont++;
        }
        printf("%d\n",cont);
        for(int i=0;i<cont;i++)
        {
            printf("%d %d %d\n",ans[i][2],ans[i][1],ans[i][0]);
        }
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值