HDU 4546 比赛难度 (优先队列 * * )

比赛难度

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 330    Accepted Submission(s): 83


Problem Description
  最近,小明出了一些ACM编程题,决定在HDOJ举行一场公开赛。
  假设题目的数量一共是n道,这些题目的难度被评级为一个不超过1000的非负整数,并且一场比赛至少需要一个题,而这场比赛的难度,就是所有题目的难度之和,同时,我们认为一场比赛与本场题目的顺序无关,而且题目也不会重复。
  显而易见,很容易得到如下信息:
  假设比赛只用1个题目,有n种方案;
  假设比赛使用2个题目,有(n-1)*n/2种方案;
  假设比赛使用3个题目,有(n-2)*(n-1)*n/6种方案;
  ............
  假设比赛使用全部的n个题目,此时方案只有1种。
  
  经过简单估算,小明发现总方案数几乎是一个天文数字!
  为了简化问题,现在小明只想知道在所有的方案里面第m小的方案,它的比赛难度是多少呢?
 
Input
输入数据的第一行为一个整数T(1 <= T <= 20),表示有T组测试数据。
每组测试数据第一行为两个整数n, m(0 < n, m <= 10000),表示现在有n个题目,现在要求第m小的方案的比赛难度。接下来第二行有n个数字,分别表示这n个题目的难度值。
 
Output
对于每组测试数据,输出一行"Case #c: ans"(不包含引号),ans 表示要求的第m小的比赛难度,输入数据保证存在第m小的方案,具体参见样例。
 
Sample Input
2 5 6 1 1 1 1 1 5 25 1 2 3 4 5
 
Sample Output
Case #1: 2 Case #2: 11
 
Source
 
Recommend
liuyiding
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>

using namespace std;

int n,m,num[10010],res[10010];

struct node{
    int cursum;     //当前和
    int nextsum;    //加入下一个元素的和
    int id;         //下一个元素的下标
    node(){}
    node(int _cur,int _next,int _id):cursum(_cur),nextsum(_next),id(_id){}
    bool operator < (const node &a) const{
        return a.nextsum<nextsum;
    }
};

int solve(){
    priority_queue<node> q;
    while(!q.empty())
        q.pop();
    num[n]=0;   
    node cur;
    cur.cursum=0;   cur.nextsum=num[0];     cur.id=0;
    q.push(cur);
    int cnt=0;
    while(cnt<m){
        cur=q.top();
        q.pop();
        if(cur.id>=n)
            continue;
        q.push(node(cur.cursum,cur.cursum+num[cur.id+1],cur.id+1));
        q.push(node(cur.nextsum,cur.nextsum+num[cur.id+1],cur.id+1));
        cnt++;
    }
    for(m=0;!q.empty();m++){
        res[m]=q.top().cursum;
        q.pop();
    }
    sort(res,res+m);
    return res[m-1];
}

int main(){

    //freopen("input.txt","r",stdin);

    int t,cases=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d",&num[i]);
        sort(num,num+n);
        int ans=solve();
        printf("Case #%d: %d\n",++cases,ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jackge/p/3086411.html