给定k个序列s1,s2,s3,...,sk,用二路合并方法将k个序列合并为一个。假设将任意两个长度分别为n和m的序列合并为一个需要的代价是m+n-1,设计一个算法来确定合并这些序列的合并为一个的最大代价和最小代价。

#include<iostream>
using namespace std;

void swap(int &a ,int &b){
	int temp=a;
	a=b;
	b=temp;
}
//返回数组arr[]的最大值

void maxSink(int arr[],int n,int i){
	int child;
		int j=i;
		while(j<=n/2){
			child=j*2;
			if((child!=n)&&arr[child+1]>arr[child])
				child=child+1;
			if(arr[child]>arr[j])
				swap(arr[child],arr[j]);
			j=child;
		}
}

void buildMax(int arr[],int n){
	//该循环为初始堆的建立,从最后一个分支节点开始
	for(int i=n/2;i>=1;i--){
		maxSink(arr,n,i);
	}
}
//返回数组的最小值

void minSink(int arr[],int n,int i){
	int j=i,child;
		while(j<=n/2){
			child=j*2;
			if((child!=n)&&arr[child+1]<arr[child])
				child=child+1;
			if(arr[child]<arr[j])
				swap(arr[child],arr[j]);
			j=child;
		}
}
void buildMin(int arr[],int n){
	for(int i=n/2;i>=1;i--){
		minSink(arr,n,i);
	}
}

int getMaxsum(int arr[],int n){
	int fir=arr[1];
	swap(arr[1],arr[n]);
	maxSink(arr,n-1,1);
	int sec=arr[1];
	arr[1]=fir+sec;
	maxSink(arr,n-1,1);
	return fir+sec-1;
}
int getMinsum(int arr[],int n){
	int fir=arr[1];
	swap(arr[1],arr[n]);
	minSink(arr,n-1,1);
	int sec=arr[1];
	arr[1]=fir+sec;
	minSink(arr,n-1,1);
	return fir+sec-1;
}



int main(){
	int n,cinNum;
	int maxHeap[1005];
	int minHeap[1005];
	while(cin>>n&&n!=0){
		for(int i=1;i<=n;i++){
			cin>>cinNum;
			maxHeap[i]=minHeap[i]=cinNum;
		}
		buildMax(maxHeap,n);
		buildMin(minHeap,n);
		int max,min;
		max=min=0;
		for(int i=0;i<n-1;i++){
			max+=getMaxsum(maxHeap,n-i);
			min+=getMinsum(minHeap,n-i);
		}
		cout<<max<<" "<<min<<endl;
	}
	return 0;
}

posted on 2011-10-20 16:07  geeker  阅读(1458)  评论(1编辑  收藏  举报