E - 最优合并问题

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\n",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\n",MAX, MIN);
    return 0;
}

posted @ 2020-10-20 19:49  洛沐辰  阅读(773)  评论(0编辑  收藏  举报