Codeforces 884D Boxes and Balls(赫夫曼编码,优先队列)
题目链接 题目大意:某人有n个不同的盒子,第一个盒子包含一些球,这些球有n个颜色,某人想要玩一个游戏,他想要把这些球分配到一个盒子里用以下的方式,第i个盒子包含颜色是i的所有球,为了完成这个,某人每轮的动作是首先选择一个非空的盒子把其中所有的球取出,然后某人选择任意k个空盒子(上一步中空出来的盒子也可以选择),把他从上一步中取出的球分成k个组,把每一组放进一个盒子,k可以等于3或者2,罚时是每一轮第一步他取出的球的个数,总罚时就是他将这些球放进相应盒子里的每一轮的罚时之和 解题思路:逆向思维,分配球的时候罚时最少,也就是说要是把已经分配好的球按照之前分配的逆方式收集起来的时候罚时也是最少的,也就是说每个盒子里的球出现的频率相加是最少的,每三个盒子收集比2+2这种方式要好,因为比如三个盒子里球的个数为a1,a2,a3如果是第一种方式罚时就是a1+a2+a3,第二种罚时是a1+a2+a1+a2+a3,n为奇数是可以一直采用3这种收集方式的,但是偶数的时候就一定会出现一次2,这个2出现的越早越好,想法来自赫夫曼编码的启发,如果是偶数push一个0进入优先队列,这样就相当于2出现在第一次 AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
using namespace std ;
priority_queue<long long ,vector <long long > ,greater<long long > > pq;
int main()
{
int n;
long long ans=0 ;
cin >>n;
if (n%2 ==0 )
pq.push(0 );
for (int i=0 ;i<n;i++)
{
int x;
cin >>x;
pq.push(x);
}
while (pq.size()!=1 )
{
long long a1,a2,a3;
long long temp;
a1=pq.top();
pq.pop();
a2=pq.top();
pq.pop();
a3=pq.top();
pq.pop();
temp=a1+a2+a3;
pq.push(temp);
ans+=temp;
}
cout <<ans<<endl;
return 0 ;
}