UVA 10954 Add All 全部相加 (Huffman编码)

题意:给你n个数的集合,每次选两个删除,把它们的和放回集合,直到集合的数只剩下一个,每次操作的开销是那两个数的和,求最小开销。

赤果果的Huffman码了。用两个队列类似归并排序,合并一下。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5010;
int q1[maxn];
int q2[maxn];

#define GetMin(x)if(head1>=rear1 || (head2<rear2 && q1[head1]>q2[head2])) x = q2[head2++];else x = q1[head1++];

int main()
{
    int n,x;
    while(scanf("%d",&n),n){
        int head1 = 0,rear1 = n,head2 = 0,rear2 = 0;
        for(int i = 0; i < n; i++) scanf("%d",q1+i);
        int ans = 0;

        sort(q1,q1+n);
        int a = q1[head1++];
        int b = q1[head1++];
        ans += q2[rear2++] = a+b;
        for(int i = 2; i < n; i++){
            GetMin(a) GetMin(b)
            ans += q2[rear2++] = a+b;
        }
        printf("%d\n",ans);
    }
    return 0;
}

效率要求不高的时候可以用优先队列

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n,x;
    while(~scanf("%d",&n)&&n){
        priority_queue<int,vector<int>,greater<int> >q;
        for(int i = 0; i < n ;i++) { scanf("%d",&x); q.push(x); }
        int ans = 0;
        for(int i = 1; i < n; i++){
            int a = q.top(); q.pop();
            int b = q.top(); q.pop();
            ans += a+b;
            q.push(a+b);
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-13 15:32:18

UVA 10954 Add All 全部相加 (Huffman编码)的相关文章

uva 10954 Add All(哈弗曼编码)

这道题我一开始想错了,这么简单的题都wa了两发...我往贪心上面想了,每次都找一个最小的数相加,结果就是 排序后直接往后加,还在那纳闷为何出错...其实这道题是哈弗曼编码问题,简直是模板题目,就是每次找两个最 小的结点求和后把他们的和放到节点中去,把这两个点删除...用的multiset,其实和set容器差不多,就是可 以存放重复的元素... 代码: #include<iostream> #include<cstdio> #include<cstdlib> #inclu

uva 10954 Add All(排序)

uva 10954 Add All Yup!! The problem name reflects your task; just add a set of numbers. But you may feel yourselves condescended, to write a C/C++ program just to add a set of numbers. Such a problem will simply question your erudition. So, let's add

UVA - 10954 - Add All (贪心)

UVA - 10954 Add All Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem F Add All Input: standard input Output: standard output Yup!! The problem name reflects your task; just add a set of numbers.

UVA - 10954 Add All (全部相加)(Huffman编码 + 优先队列)

题意:有n(n <= 5000)个数的集合S,每次可以从S中删除两个数,然后把它们的和放回集合,直到剩下一个数.每次操作的开销等于删除的两个数之和,求最小总开销.所有数均小于10^5. 分析:按此操作,最终变成1个数,需要n-1次操作,要想总开销最小,就使每次取出的两数之和最小,优先队列. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstrin

【NOIP合并果子】uva 10954 add all【贪心】——yhx

Yup!! The problem name reects your task; just add a set of numbers. But you may feel yourselvescondescended, to write a C/C++ program just to add a set of numbers. Such a problem will simplyquestion your erudition. So, lets add some avor of ingenuity

UVa 10954 Add All 贪心

贪心   每一次取最小的两个数,注意相加的数也要算' #include<cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<queue> using namespace std; int main() { long long a[5005],i; long long b[5005],n; priority_

【uva 10954】Add All(算法效率+Huffman编码+优先队列)

题意:有N个数,每次选2个数合并为1个数,操作的开销就是这个新的数.直到只剩下1个数,问最小总开销. 解法:合并的操作可以转化为二叉树上的操作[建模],每次选两棵根树合并成一棵新树,新树的根权值等于两棵合并前树的根权值和(也与Huffman编码的建立过程类似,选权值最小的两棵树). 这样总开销就是除了叶子结点的权值和  => 每个叶子结点的权值*层数(根节点层数为0)之和  => WPL(树的所有叶子节点的带权路径长度之和,即该节点到根节点路径长度与节点上权的乘积之和). 而Huffman树就

UVa10954 Add All (Huffman编码,优先队列)

链接:http://vjudge.net/problem/UVA-10954 分析:Huffman编码建立过程,每次贪心选取两个当前最小数,从集合中删去,然后把它们的和放回集合,用优先队列去模拟集合而且可以优化取最小数过程. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 6 const int maxm = 500 + 5; 7 8 int

UVa 10954,Add All

Huffman编码简化版,优先队列搞定. 1A 调试的时候发现一个问题..木有想明白...问题代码里给出,哪位大神给解释下. #include <iostream> #include <queue> #define maxn 5000+5 using namespace std; int n; int ans; priority_queue<int, vector<int>, greater<int> >qi; int main() { whil