[SSL] 1040 2004 Divisional League Improvement Group 2 Merged Fruit

[SSL] 1040 2004 Divisional League Improvement Group 2 Merged Fruit

Time Limit:20000MS Memory Limit:65536K
Case Time Limit:5000MS

Description

In an orchard, Duoduo had already knocked down all the fruits, and divided them into different piles according to different types of fruits. Duoduo decided to combine all the fruits into one pile.
  Every time you merge, Toto can merge two piles of fruits together, and the energy consumed is equal to the sum of the weight of the two piles of fruits. It can be seen that after all the fruits are merged n-1 times, there is only one pile left. The total stamina consumed by Duoduo when merging the fruits is equal to the sum of the stamina consumed for each merge.
  Because it will take great effort to move these fruits home, Duoduo should save as much energy as possible when merging the fruits. Assuming that the weight of each fruit is 1, and the number of fruit types and the number of each fruit are known, your task is to design a combined sequence plan to minimize the amount of physical effort that Duoduo consumes, and output the minimum value of physical strength.
  For example, there are 3 kinds of fruits, the numbers are 1, 2, and 9. You can merge piles 1 and 2 first, the number of new piles is 3, and the physical effort is 3. Then, merge the new pile with the original third pile, and get a new pile, the number is 12, and the physical effort is 12. So Toto consumes a total of stamina=3+12=15. It can be proved that 15 is the minimum physical expenditure value.

Input

The input consists of two lines. The first line is an integer n (1<=n<=10000), which indicates the number of fruit types. The second line contains n integers, separated by spaces. The i-th integer ai (1<=ai<=20000) is the number of the i-th fruit.

Output

The output includes one line, and this line only contains an integer, which is the minimum physical exertion value. Input data to ensure that this value is less than 231.

Sample Input

3 
1 2 9 

Sample Output

15

Hint

For 30% of the data, it is guaranteed that n<=1000:
For 50% of the data, it is guaranteed that n<=5000;
for all the data, it is guaranteed that n<=10000.

Ideas

Use heap.
Build a pile first.
Heap sorting
Take out the top 2 of the heap each time, sum them, and insert them into the heap

Code

Handwriting pile

#include<iostream>
#include<cstdio>
using namespace std;
int h[100010];
class heapmn
{
    
    
	private:
	public:
		void heapup(int n,int x);//上移操作,把h[x]上移的合适位置
		void heapdown(int n,int x);//下移操作,把h[x]下移的合适位置
		void heapinsert(int &n,int x);//插入操作,把x加入堆的合适位置 
		void heapdelete(int &n,int x);//删除操作,删除h[x]
		void heapsort(int &n);//堆排序 
		void heapbuild(int &n,int m);//建堆 
		void swap(int &t1,int &t2);//交换两数
};
void heapmn::swap(int &t1,int &t2)//交换两数 
{
    
    
	int t=t1;
	t1=t2,t2=t;
	return;
}
void heapmn::heapup(int n,int x)//上移操作,把h[x]上移的合适位置 
{
    
    
	if(x>n)return;
	for(;x>1;x>>=1)
		if(h[x]<h[x>>1]) swap(h[x],h[x>>1]);
		else return;
	return;
}
void heapmn::heapdown(int n,int x)//下移操作,把h[x]下移的合适位置
{
    
    
	if(x<1)return;
	for(x<<=1;x<=n;x<<=1)
	{
    
    
		x+=(x+1<=n&&h[x+1]<h[x]);
		if(h[x]<h[x>>1]) swap(h[x>>1],h[x]);
		else return;
	}
	return;
}
void heapmn::heapinsert(int &n,int x)//插入操作,把x加入堆的合适位置 
{
    
    
	h[++n]=x;
	heapup(n,n);
	return;
}
void heapmn::heapdelete(int &n,int x)//删除操作,删除h[x] 
{
    
    
	if(h[n]<=h[x]) h[x]=h[n--],heapup(n,x);
	else h[x]=h[n--],heapdown(n,x);
	return;
}
void heapmn::heapsort(int &n)//堆排序 
{
    
    
	for(;n;h[1]=h[n--],heapdown(n,1))
	{
    
    
		//a[i]=h[1];
		printf("%d ",h[1]);
	}
	return;
}
void heapmn::heapbuild(int &n,int m)//建堆 
{
    
    
	int i;
	for(n=0,i=1;i<=m;i++)
	{
    
    
	    //h[++n]=a[i];
		scanf("%d",&h[++n]);
	    heapup(n,n);
	}
	return;
}
int main()
{
    
    
	heapmn heap;
	int n,i,ans=0,tem;
	scanf("%d",&n);
	heap.heapbuild(n,n);
	while(n>1)
	{
    
    
		tem=h[1];
		heap.heapdelete(n,1);
		tem+=h[1];
		ans+=tem;
		heap.heapdelete(n,1);
		heap.heapinsert(n,tem);
	}
	printf("%d",ans);
	return 0;
}

STL

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
priority_queue <int> que;
int main()
{
    
    
	int n,i,ans=0,tem;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
    
    
		scanf("%d",&tem);
	    que.push(-tem);
	}
	for(i=1;i<n;i++)
	{
    
    
		tem=-que.top();
		que.pop();
		tem-=que.top();
		que.pop();
		ans+=tem;
		que.push(-tem);
	}
	printf("%d",ans);
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_46975572/article/details/113113541