Gym - 101234G Dreamoon and NightMarket结题报告(集合元素的组合中第K大的值)

本文介绍了一种求解集合元素所有组合中第K大的值的经典算法。通过先排序元素,然后使用优先队列进行状态转移,实现了对组合价值的高效计算。此方法适用于物品价值求和问题。

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

题意:给你n种物品的价值,让你求这些物品组合的第k大的集合的值(集合内放的是物品种类,不得重复,但价值可以重复)、

思路:这是一类经典的问题求集合元素所有组合中第K大的值。

具体的步骤如下:

(1)首先将储存元素的数组排序;

(2)假设当前组合中最后一个元素的下标为 i , 考虑为以i为最后一个元素的全排列都举过了。那么从当前组合(sum, i)到下一个最小组合有两种可能:减去本身再加上后一个,直接加上后一个。

 这个图可以说明我们思路的正确性,也类似于DFS思想不过变得更为简洁。(图是盗的嘿嘿)

 

下面直接给出AC代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn=2*1e5+100;
const double eps=1e-6;
typedef long long ll;
typedef pair<ll,int> P;
priority_queue<P,vector<P>,greater<P> > que;
int n,k;
int a[maxn];

void solve()
{
    que.push(make_pair(a[0],0));

    int cnt=0;
    while(true)
    {
        int idx=que.top().second;
        ll sum=que.top().first;

        if(idx<n-1)
        {
            que.push(make_pair(sum+a[idx+1],idx+1));
            que.push(make_pair(sum-a[idx]+a[idx+1],idx+1));
        }

        que.pop();
        cnt++;
        if(cnt==k)
        {
            printf("%lld",sum);
            break;
        }

    }
}


int main()
{
    scanf("%d %d",&n,&k);

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

    sort(a,a+n);

    solve();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值