4J - 前m大的数

还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。

Input

输入可能包含多组数据,其中每组数据包括两行: 
第一行两个数N和M, 
第二行N个数,表示该序列。 

Output

对于输入的每组数据,输出M个数,表示结果。输出应当按照从大到小的顺序排列。

Sample Input

4 4
1 2 3 4
4 5
5 3 6 4

Sample Output

7 6 5 5
11 10 9 9 8

// 算法错误.
// 例如:要从序列10,9,9,0,0,0中输出前4大的数,结果应该是10+9,10+9,9+9,10+0
// 而此算法不会输出10+0,而会输出9+0
 1 #include <stdio.h>
 2 #include <algorithm>
 3 using namespace std;
 4 bool cmp(int a, int b)
 5 { return a>b; }
 6 int main()
 7 {
 8     int n, m, a[3000], i, j, k, x1, x2, flag;
 9     while(scanf("%d %d", &n, &m)!=EOF)
10     {
11         for(i=0;i<n;i++)
12             scanf("%d", &a[i]);
13         sort(a,a+n,cmp);
14         flag=0;
15         for(j=0;j<n-2;j++)
16         {
17             x1=a[j];
18             for(k=j+1;k<n;k++)
19             {
20                 x2=a[k];
21                 if(x1+x2>=a[j+1]+a[j+2])
22                 {
23                     flag++;
24                     if(flag==m) 
25                     { printf("%d\n", x1+x2); break; }
26                     else printf("%d ", x1+x2);
27                 }
28                 else break;
29             }
30             if(flag==m) break;
31         }
32         if(flag!=m) printf("%d\n", a[j]+a[j+1]);
33     }
34     return 0;
35 }
WA
// 另开了一个数组存所有和,然后对这个数组排序
 1 #include <stdio.h>
 2 
 3 void shell_sort(int a[], int len)
 4 {
 5     int i,j, gap, t;
 6     for(gap=len/2; gap>0; gap/=2)
 7         for(i=gap; i<len; i++)
 8             for(j=i;j-gap>=0&&a[j]>a[j-gap];j-=gap)
 9             { t=a[j-gap]; a[j-gap]=a[j]; a[j]=t; }
10 }
11 int a[3000],b[4500000];
12 int main()
13 {
14     int n, m, i,j,k;
15     while(scanf("%d %d", &n, &m)!=EOF)
16     {
17         for(i=0;i<n;i++)
18             scanf("%d", &a[i]);
19         i=0;
20         for(j=0;j<n-1;j++)
21             for(k=j+1;k<n;k++)
22             { b[i]=a[j]+a[k]; i++; }
23         shell_sort(b,n*(n-1)/2);
24         for(i=0;i<m-1;i++)
25             printf("%d ",b[i]);
26         printf("%d\n", b[i]);
27     }
28     return 0;
29 }
Time Limit Exceeded
// 另开一个数组,初始所有元素为0. 用下标表示和,值为和的个数.
// 不用排序,直接对数组遍历. 值大于零就输出下标(即和),并统计输出个数.
 1 #include <stdio.h>
 2 int main()
 3 {
 4     int n, m, a[3000];
 5     while(scanf("%d %d", &n, &m)!=EOF)
 6     {
 7         int b[10001]={0};
 8         for(int i=0;i<n;i++)
 9             scanf("%d", &a[i]);
10         for(int j=0;j<n-1;j++)
11             for(int k=j+1;k<n;k++)
12                 b[a[j]+a[k]]++;
13         int j=0, flag=0;
14         for(int i=10000;;i--)
15             if(b[i])
16             {
17                 while(b[i]--)
18                 {
19                     j++;
20                     if(j==m)
21                     { printf("%d\n", i); flag=1; break; }
22                     else printf("%d ", i);
23                 }
24                 if(flag) break;
25             }
26     }
27     return 0;
28 }
AC

 

posted @ 2019-02-08 13:20  Blind  阅读(270)  评论(0编辑  收藏  举报