hdu 4546 输入n个数 问这n个数相加组成的第K小的数是什么

比赛难度

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


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
 


思路 :

用一个结构体

struct haha
{
    int sum;//当前的大小
    int nextsum;//如果加上下一个值总的sum大小
    int nextid;//下一个值对应的id
    bool operator<(const struct haha &b)const
    {return b.nextsum < nextsum;}//按照nextsum,较小的优先出队 这样每次优先队列pop出的值都会保证是最小的 因为pop出的结构体对应的sum加上下一个数值(即nextsum)是最小的
}temp,q;

 

在pop后   是否加上a[ith]都要考虑进去

 

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
int n,m,a[11111],k;
struct haha
{
    int sum;
    int nextsum;
    int nextid;
    bool operator<(const struct haha &b)const
    {return b.nextsum < nextsum;}
}temp,q;
void solve()
{
    sort(a,a+n);
    priority_queue<struct haha>que;
    q.sum=0;q.nextsum=a[0];q.nextid=0;
    que.push(q);
    int cnt=0;
    a[n]=0;
    while(cnt<m)
    {
        temp=que.top();
        que.pop();
        if(temp.nextid>=n) continue;
        q.sum=temp.sum;q.nextsum=temp.sum+a[temp.nextid+1];q.nextid=temp.nextid+1;
        que.push(q);
        q.sum=temp.nextsum;q.nextsum=temp.nextsum+a[temp.nextid+1];q.nextid=temp.nextid+1;
        que.push(q);
        cnt++;
    }
     for(int i = 0; !que.empty(); i ++) {a[i] = que.top().sum; que.pop();}
     sort(a,a+m);
     printf("Case #%d: %d\n",k,a[m-1]);
}
int main()
{
    int cas,i,j;
    scanf("%d",&cas);
    while(cas--)
    {
        k++;
        scanf("%d %d",&n,&m);
        for(i=0;i<n;i++) scanf("%d",&a[i]);
        solve();
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值