POJ 2442.Sequence
2015-07-14
问题简述:
输入 m 条序列,每条序列有 n 个整数。对每一个序列取一个数,可随机取出 m 个数,求这 m 个数的和,会有 m^n 种情况,输出其中和最小的 n 个数。
原题链接:http://poj.org/problem?id=2442
解题思路:
暴力求解会遍历 m^n 次,时间复杂度太高,不适合这个题,故采用其他方法,比如堆。
运算过程中,我们只需要维护好大小为 n 的堆,以实现最后这个堆就是所求 n 个数。
构造一个和序列 sum,初始化和序列 sum 为第一个序列;
从第二个序列开始,对每一个序列计算下一个序列的第一个数与当前和序列的和,存在一个新序列 ans 中。
用下一个序列的下一个数与当前和序列的每一个数相加,将和值与 ans 比较,若小于 ans 中的最大数,则将此和值插入 ans。
注:以上过程每一次使用一个新序列时,都需要对其进行升序排列。
源代码:
1 /* 2 OJ: POJ 3 ID: 3013216109 4 TAST: 2442.Sequence 5 LANG: C++ 6 NOTE: STL堆 7 */ 8 #include <cstdio> 9 #include <algorithm> 10 using namespace std; 11 12 const int MAX_M=105,MAX_N=2005; 13 int a[MAX_M][MAX_N]; 14 int sum[MAX_N],ans[MAX_N]; 15 16 int main() 17 { 18 int t,m,n,i,j,k; 19 scanf("%d",&t); 20 while(t--) { 21 scanf("%d %d",&m,&n); 22 for(i=0;i<m;i++) 23 for(j=0;j<n;j++) 24 scanf("%d",&a[i][j]); 25 for(j=0;j<n;j++) 26 sum[j]=a[0][j]; 27 28 for(i=1;i<m;i++) { 29 sort(sum,sum+n); 30 sort(a[i],a[i]+n); 31 for(k=0;k<n;k++) 32 ans[k]=sum[k]+a[i][0]; 33 make_heap(ans,ans+n); 34 for(j=1;j<n;j++) { 35 for(k=0;k<n;k++) { 36 int x=sum[k]+a[i][j]; 37 if(x<ans[0]) { 38 pop_heap(ans,ans+n); 39 ans[n-1]=x; 40 push_heap(ans,ans+n); 41 } 42 else break; 43 } 44 } 45 for(j=0;j<n;j++) 46 sum[j]=ans[j]; 47 } 48 sort(sum,sum+n); 49 for(j=0;j<n-1;j++) 50 printf("%d ",sum[j]); 51 printf("%d\n",sum[n-1]); 52 } 53 return 0; 54 }