题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4546
Problem Description
最近,小明出了一些ACM编程题,决定在HDOJ举行一场公开赛。
假设题目的数量一共是n道,这些题目的难度被评级为一个不超过1000的非负整数,并且一场比赛至少需要一个题,而这场比赛的难度,就是所有题目的难度之和,同时,我们认为一场比赛与本场题目的顺序无关,而且题目也不会重复。
显而易见,很容易得到如下信息:
假设比赛只用1个题目,有n种方案;
假设比赛使用2个题目,有(n-1)*n/2种方案;
假设比赛使用3个题目,有(n-2)*(n-1)*n/6种方案;
............
假设比赛使用全部的n个题目,此时方案只有1种。
经过简单估算,小明发现总方案数几乎是一个天文数字!
为了简化问题,现在小明只想知道在所有的方案里面第m小的方案,它的比赛难度是多少呢?
假设题目的数量一共是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个题目的难度值。
每组测试数据第一行为两个整数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
这个题目说一下怎么理解吧。给你一个排好序的数组,怎么尽可能快的将最小的组合数挑选出来,这就是这个题目的关键!!
比如给你一个数组a[5]={1 ,2 ,3 ,4 ,5};
a[0]肯定是最小的数对吧,a[1]是第二小的数,这个是毋庸置疑的!
但是第三小的数是多少呢?是a[2]还是a[0]+a[1];这个我们就不知道了对吧,但是一定是这两个中的一个对吧,这就是这个题目的突破口!!
代码:
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
struct node{
int sum,nextsum,nextid;
friend bool operator<(node A,node B){
return A.nextsum>B.nextsum;
}
}stu,tmp;
int a[10005];
int main()
{
int t,n,m,Case=1;
cin>>t;
while(t--){
cin>>n>>m;
priority_queue<node>q;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
stu.sum=0; // 初始状态;
stu.nextsum=a[0];
stu.nextid=0;
q.push(stu);
int cnt=0;
while(!q.empty()){
stu=q.top();
q.pop();
if(stu.nextid>=n) continue;
tmp.sum=stu.sum; // 隔一个,直接加下一个;
tmp.nextsum=stu.sum+a[stu.nextid+1];
tmp.nextid=stu.nextid+1;
q.push(tmp); // 不隔,直接加
tmp.sum=stu.nextsum;
tmp.nextsum=stu.nextsum+a[stu.nextid+1];
tmp.nextid=stu.nextid+1;
q.push(tmp);
cnt++;
if(cnt==m){
cout<<"Case #"<<Case++<<": "<<stu.nextsum<<endl;
break;
}
}
}
return 0;
}