1. 程式人生 > >101234G Dreamoon and NightMarket 求第K大集合

101234G Dreamoon and NightMarket 求第K大集合

1.題意:給你n種物品的價值,讓你求這些物品組合的第k大的集合的值(集合內放的是物品種類,不得重複,但價值可以重複)

2.分析:歸結為一類經典問題,求第K大集合

(1)將陣列排序

(2)假設當前組合中最後一個元素的下標為 i , 考慮為以i為最後一個元素的全排列都舉過了。那麼從當前組合(sum, i)到下一個最小組合有兩種可能:

若 i < n:

  • sum + value[i+1]  , i+1
  • sum - value[ i ] + value[i + 1] , i+1

(3)圖示

不難發現:不重不漏,優先佇列儲存,輸出第k個即可

3.程式碼:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> P;
const int maxn = 100000 + 7;
int num[2*maxn];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i = 0;i<n;i++){
        scanf("%d",&num[i]);
    }
    sort(num,num+n);
    priority_queue<P,vector<P> , greater<P> >que;
    que.push(P(num[0],0));
    int len = 0;
    while(!que.empty()){
        P p = que.top();
        que.pop();
        if(++len==k){
            printf("%lld\n",p.first);
            return 0;
        }
        if(p.second + 1 < n){
            que.push(P(p.first + num[p.second + 1] , p.second + 1));
            que.push(P(p.first - num[p.second] + num[p.second + 1],p.second + 1));
        }

    }
    return 0;
}