发现是去年做过的题
今年拿出来用别的方法又做了一遍,正好练习一下min/max_element()
霍夫曼树的构造费用问题
果然 min_element就是好用(节省大量思维量)
题目描述:
Huffman树在编码中有着广泛的应用。 在这里,我们只关心Huffman树的构造过程。 给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程如下:
- 找到{pi}中最小的两个数,设为pa和pb,将pa和pb从{pi}中删除掉,然后将它们的和加入到{pi}中。这个过程的费用记为pa + pb。
- 重复步骤1,直到{pi}中只剩下一个数。 在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用。 本题任务:对于给定的一个数列,现在请你求出用该数列构造Huffman树的总费用。 例如,对于数列{pi}={5, 3, 8, 2, 9},Huffman树的构造过程如下:
- 找到{5, 3, 8, 2, 9}中最小的两个数,分别是2和3,从{pi}中删除它们并将和5加入,得到{5, 8, 9, 5},费用为5。
- 找到{5, 8, 9, 5}中最小的两个数,分别是5和5,从{pi}中删除它们并将和10加入,得到{8, 9, 10},费用为10。
- 找到{8, 9, 10}中最小的两个数,分别是8和9,从{pi}中删除它们并将和17加入,得到{10, 17},费用为17。
- 找到{10, 17}中最小的两个数,分别是10和17,从{pi}中删除它们并将和27加入,得到{27},费用为27。
- 现在,数列中只剩下一个数27,构造过程结束,总费用为5+10+17+27=59。
输入:
输入的第一行包含一个正整数n(n<=100)。 接下来是n个正整数,表示p0, p1, …, pn-1,每个数不超过1000。
输出:
输出用这些数构造Huffman树的总费用。
--------------------------------------------------------------
样例输入
5 5 3 8 2 9
样例输出
59
--------------------------------------------------------------------------
思路:1.首先做一个min_element()和eraser()的寻找删除函数 、留下a、b每次找出后加到this_sum里push_back()进去,最后每轮sum=sum+this_sum (min_element思路)
or
2.先sort()完之后用迭代器取出来(第二个迭代器直接+1)、加起来、放进去、pop掉后两位 emm ...不赘述 (sort思路)(补充:sort方法具体操作可以参考这个人博客 https://blog.csdn.net/weixin_42274148/article/details/80406661)
#include <bits/stdc++.h>
using namespace std;
vector<int> v;
int Sum(){
int a1,a2;
vector<int>::iterator iter;
int sum=0,this_sum;
while(v.size() > 1){
iter=min_element(v.begin(),v.end());
a1=*iter;
v.erase(iter);
iter=min_element(v.begin(),v.end());
a2=*iter;
v.erase(iter);
this_sum = a1+a2;
v.push_back(this_sum);
a1=0;
a2=0;
sum=sum+this_sum;
}
// sum=sum+*min_element(v.begin(),v.end()); //最后一位并不用加起来...因为霍夫曼树构建的原理、最后还会返回一个原值,而那个显然是不属于“费用”的
return sum;
}
int main()
{
int n;
int a,b;
scanf("%d",&n);
for(;n>0;n--)
{
cin>>a;
v.push_back(a);
}
b=Sum();
cout<<b;
return 0;
}
再给一个全放main里健壮性强的,一步一步易于理解(就不用写题解了哈哈哈(补:最后还是写上了题解、而且请注意我是先写出调用方法再都拉到主函数里的、这里从养成良好习惯的角度不建议直接都往主函数里塞))
#include <bits/stdc++.h>
using namespace std;
vector<int> v;
int main()
{
int n;
int a,b;
scanf("%d",&n);
for(;n>0;n--) //经实验,--n与n--等效(循环相同次数)
{
cin>>a;
v.push_back(a);
}
int a1,a2;
vector<int>::iterator iter;
int sum=0,this_sum=0;
while(v.size() > 1){
iter=min_element(v.begin(),v.end());
a1=*iter;
// cout<< a1<<endl; //a1能传过去
v.erase(iter);
iter=min_element(v.begin(),v.end());
a2=*iter;
// cout<< a2<<endl; //a2也能传过去
v.erase(iter);
this_sum = a1+a2;
v.push_back(this_sum);
// cout<< this_sum<<endl; // thissum也能传
a1=0; //功能可用
a2=0; //功能可用
sum=sum+this_sum; //.......妈耶sum忘了赋初值
// cout<<sum<<endl;
}
cout<<sum;
return 0;
}