欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-04 18:51:31
...

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)
Educational Codeforces Round 31-k叉哈夫曼&优先队列&好题-D. Boxes And Balls
Educational Codeforces Round 31-k叉哈夫曼&优先队列&好题-D. Boxes And Balls