Description
给定k 个排好序的序列s1 , s2,……, sk , 用2 路合并算法将这k 个序列合并成一个序列。假设所采用的2 路合并算法合并2 个长度分别为m和n的序列需要m + n -1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。
为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
对于给定的k个待合并序列,计算最多比较次数和最少比较次数合并方案。
Input
输入数据的第一行有1 个正整数k(k≤1000),表示有k个待合并序列。接下来的1 行中,有k个正整数,表示k个待合并序列的长度。
Output
输出两个整数,中间用空格隔开,表示计算出的最多比较次数和最少比较次数。
Sample
Input
4
5 12 11 2
Output
78 52
题解:
哈夫曼问题,分别取最大值做哈夫曼树和最小值做哈夫曼树,然后带权节点*路径长度的和就是最多比较次数与最少比较次数。
涉及哈夫曼问题可用优先队列(堆)进行解题,由于考试无法使用优先队列,所以后面会补一个不用优先队列的代码。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
int maxn = 1050;
int main()
{
int n;
int i, MAX, MIN, sum;
int a[maxn];
scanf("%d",&n);
for(i=0; i<n; i++){
scanf("%d",&a[i]);
}
priority_queue<int> q1;
priority_queue<int, vector<int>, greater<int> > q2;
for(i=0; i<n; i++){
q1.push(a[i]);
q2.push(a[i]);
}
MAX = 0;
while(!q1.empty()){
sum = q1.top();
q1.pop();
if(q1.empty()){
break;
}
sum += q1.top();
q1.pop();
q1.push(sum);
MAX += sum - 1;
}
MIN = 0;
while(!q2.empty()){
sum = q2.top();
q2.pop();
if(q2.empty())
break;
sum += q2.top();
q2.pop();
q2.push(sum);
MIN += sum - 1;
}
printf("%d %d
",MAX,MIN);
return 0;
}
模拟哈夫曼树建树过程求解。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
struct tree{
int l, r, f;
int data;
};
int maxn = 2050;
int INF = 0x3f3f3f3f;
int main(){
int MIN, MAX;
int n, i, j, m1, m2, c1, c2, t;
int a[maxn];
tree b[maxn];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(i=0; i<n-1; i++){
for(j=0; j<n-i-1; j++){
if(a[j] > a[j + 1]){
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
for(i=1; i<=n; i++){
b[i].data = a[i-1];
b[i].f = b[i].l = b[i].r = 0;
}
for(i=n+1; i<=2*n-1; i++){
c1 = c2 = 0;
m1 = m2 = INF;
for(j=1; j<i; j++){
if(!b[j].f){
if(b[j].data<m1){
m2 = m1;
m1 = b[j].data;
c2 = c1;
c1 = j;
}
else if(b[j].data<m2){
m2 = b[j].data;
c2 = j;
}
}
}
b[i].data = m1 + m2;
b[i].f = 0;
b[i].l = c1;
b[i].r = c2;
b[c1].f = b[c2].f = i;
}
MIN = 0;
for(i=1; i<=n; i++){
int q = i;
int p = 0;
while(b[q].f){
p++;
q = b[q].f;
}
MIN += b[i].data * p;
}
MIN -= (n - 1);
MAX = 0;
for(i=n-1; i>=1; i--){
a[i-1] += a[i];
MAX += a[i-1];
}
MAX -= (n - 1);
printf("%d %d
",MAX, MIN);
return 0;
}