zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    
    
  • 相关阅读:
    dotnet core部署方式两则:CLI、IIS
    oracle的loop等循环语句的几个用法小例子[转]
    NET Core 环境搭建和命令行CLI入门[转]
    电视不支持AirPlay镜像怎么办?苹果iPhone手机投屏三种方法
    haproxy+keepalived实现web集群高可用性[转]
    论程序员的时代焦虑与焦虑的缓解[转]
    使用C#压缩解压rar和zip格式文件
    C#获取并修改文件扩展名的方法
    普通码农的思维总结【转】
    T4生成实体,单张表和多张表
  • 原文地址:https://www.cnblogs.com/luoxiaoyi/p/13848475.html
Copyright © 2011-2022 走看看