比赛描述
对于给定n堆石子,编程计算合并成一堆的最大总费用和最小总费用。
输入
文件的第1 行有2 个正整数n和k,表示有n堆石子,每次至少选2 堆最多选k堆石子合并。第2 行有n个数,分别表示每堆石子的个数。
输出
程序运行结束时,将计算出的最大总费用和最小总费用输出。
样例输入
7 3
45 13 12 16 9 5 22
样例输出
593 199
提示
undefined
题目来源
NUAA
/*87 MS #include<iostream> #include<set> using namespace std; int main(){ // freopen("test.txt","r",stdin); int n,k,i,num,cost; multiset<int> iSet1,iSet2; multiset<int>::iterator it; multiset<int>::reverse_iterator rIt; scanf("%d%d",&n,&k); for(i=0;i<n;i++){ scanf("%d",&num); iSet1.insert(num); iSet2.insert(num); } cost = 0; while(!iSet1.empty()){ num = 0; rIt = iSet1.rbegin(); for(i=0; !iSet1.empty() && i<2; i++){ rIt = iSet1.rbegin(); num += *rIt; iSet1.erase((++rIt).base()); } if(iSet1.size()){ iSet1.insert(num); } cost += num; } printf("%d ",cost); cost = 0; while(iSet2.size() % (k-1) != 1){ iSet2.insert(0); } while(!iSet2.empty()){ num = 0; it = iSet2.begin(); for(i=0; !iSet2.empty() && i<k; i++){ it = iSet2.begin(); num += *it; iSet2.erase(it); } if(iSet2.size()){ iSet2.insert(num); } cost += num; } printf("%d\n",cost); } */ //上面的花费时间较多,下面尝试用堆还维护最大最小信息 //19MS 2015-4-28 最优解 #include<iostream> #include<algorithm> using namespace std; void minHeapAdjust(int *a, int i, int n){ int child = (i<<1)|1; while(child<n){ if(child+1<n && a[child]>a[child+1]){ child++; } if(a[i]>a[child]){ swap(a[i],a[child]); }else{ break; } i = child; child = (i<<1)|1; } } int main(){ // freopen("test.txt","r",stdin); int n,k,i,*a,cost,c; scanf("%d%d",&n,&k); a = (int *)malloc((n+k)*sizeof(int)); for(i=0;i<n;i++){ scanf("%d",a+i); } sort(a,a+n); cost = 0; c = a[n-1]; for(i=n-2;i>=0;i--){ c += a[i]; cost += c; } printf("%d ",cost); while(n%(k-1)!=1){ a[n++]=0; } for(i=(n-1)>>1;i>=0;i--){ minHeapAdjust(a,i,n); } cost = 0; while(n>1){ c = 0; for(i=0;i<k-1;i++){ c += a[0]; a[0] = a[--n]; minHeapAdjust(a,0,n); } c += a[0]; a[0] = c; minHeapAdjust(a,0,n); cost += c; } printf("%d\n",cost); }