比赛难度
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 768 Accepted Submission(s): 263
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
Source
Recommend
思路:贪心。
由于数据很大所以不可能一个一个枚举也就是2n.
每个数选或不选。。
先把难度按升序排。
那没还是考虑每个数选或不选,由于题目只要求最大就前1000个数,所以可以把最小的找出来,也就是nandu[0];
开结构体记录当前状态下,选这个数的和,和不选这个数的和,同时记录这个数的数组下标,开优先队列,以难度升序,那么先将第一个状态入队。
然后每次取出顶层的,就是当前所有状态最小的。
然后由这个最小状态去找他的下一个状态,也就是它的后一个元素选或不选,再加入队列即可,取出的所要求的个数,就是排第几位。
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<math.h> 6 #include<queue> 7 #include<string.h> 8 #include<stack> 9 #include<vector> 10 #include<map> 11 #define sc(x) scanf("%I64d",&x) 12 #define pr(x) printf("%I64d",x) 13 #define prr(x) printf("%I64d ",x) 14 #define prrr(x) printf(" %I64d",x) 15 #define FOR(i,p,q) for(int i=p;i<=q;i++) 16 typedef struct pp 17 { 18 int x;//没有选id的状态 19 int y;//选了id的状态 20 int id; 21 bool operator<(const pp&cx)const//优先队列按难度升序排 22 { 23 return cx.y<y; 24 } 25 } ss; 26 using namespace std; 27 int nandu[10005]; 28 int main(void) 29 { 30 int n,m,i,j,k,p,q; 31 scanf("%d",&k); 32 for(i=1; i<=k; i++) 33 { 34 priority_queue<ss>que; 35 scanf("%d %d",&p,&q); 36 for(j=0; j<p; j++) 37 { 38 scanf("%d",&nandu[j]); 39 } 40 sort(nandu,nandu+p); 41 ss fi;//定义初始状态,也就是难度最小的 42 fi.x=0; 43 fi.y=nandu[0]; 44 fi.id=0; 45 que.push(fi); 46 int cc; 47 while(q--) 48 { 49 ss lk; 50 lk=que.top(); 51 if(q==0) 52 { 53 cc=lk.y; 54 } 55 que.pop(); 56 ss dd; 57 if(lk.id<p-1)//当前最小的状态 58 { 59 dd.x=lk.x;//当前最小状态没有选nandu[lk.id]; 60 dd.y=lk.x+nandu[lk.id+1]; 61 dd.id=lk.id+1; 62 que.push(dd); 63 dd.x=lk.y;//当前最小状态选nandu[lk.id] 64 dd.y=lk.y+nandu[lk.id+1]; 65 dd.id=lk.id+1; 66 que.push(dd); 67 } 68 } 69 printf("Case #%d: %d ",i,cc); 70 } 71 return 0; 72 73 }