Educational Codeforces Round 31-k叉哈夫曼&优先队列&好题-D. Boxes And Balls

来源:互联网 发布:金蝶软件操作教程 编辑:程序博客网 时间:2024/06/14 22:37

http://codeforces.com/contest/884/problem/D
给定一个n。
然后是n个不同颜色的球的数目。
开始这些球都在第一个盒子里。
你有下面的操作方法
① 把某一个不空盒子种的球拿出来。
② 把这些球按颜色装到3个或者2个盒子里,不同颜色可以装在一起。
而每次这种操作的花费为 你第一个操作拿出的球的数目。
问你如何操作,能够使花费最小。


一点都不显然,这时一个k叉哈夫曼,我也是画图才发现。随着哈夫曼树叉树的增加,他的最小带权路径长度也再慢慢变小。但是编码所需字符集也在慢慢增多。所以这道题就是构造三叉哈夫曼就阔以了。
k叉哈夫曼的构造方法(by 大佬):
构造的思路。
每次选择最小的k个来放置。
但是容易发现最后可能不够k个,那怎么办捏
假设有n个节点,k叉,最后剩一个。
容易得到,n-1是k-1的倍数。
如果(n-1)%(k-1)!=0,
那么就要再放入(k-1-(n-1)%(k-1))个虚拟点,
并且它们的权值为0,它们也参与求最小k个点。
其实就是加点了。

  #include <bits/stdc++.h>using namespace std;/* */typedef long long ll;struct cmp{  bool operator()(ll x,ll y){      return x>y;  }};priority_queue<ll,vector<ll>,cmp>q;int t;ll a;int main() {    while(~scanf("%d",&t)){          ll sum=0;          while(!q.empty()) q.pop();          for(int i=0;i<t;i++){             scanf("%lld",&a);             q.push(a);          }          if((t-1)%2!=0){            int x=(2-(t-1)%2);            for(int i=0;i<x;i++)                q.push(0);          }          while(q.size()>=3){                ll a=0;                ll u1=q.top();q.pop();                a+=u1;                ll u2=q.top();q.pop();                a+=u2;                ll u3=q.top();q.pop();                a+=u3;                sum+=a;                q.push(a);          }          printf("%lld\n",sum);    }    return 0;}

有巨佬的写法貌似不是这样,但是思路是一样的,大佬没有加点,但是在剩余节点为偶数的情况下选择只取2个最小的。(其实是一样的,经过我手算发现只有偶数的第一次可以出现这种情况,而也只有这种情况是加0 的,并且只加一个0,巧了,另一个大佬的代码就是酱紫,根据t的奇偶性,如果是偶数就加一个qwq)
这里写图片描述
这里写图片描述

阅读全文
0 0
原创粉丝点击