SSLOJ1040&P1090 2004 Divisional League Improvement Group 2 Merged Fruit & [USACO06NOV] Fence Repair G

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

Ideas

So is it CCF plagiarism or USACO?
Obviously a greedy algorithm, each time the smallest 2 stacks are merged.
Then use the heap/priority queue to optimize the time.
Heap code:

#include<iostream>
#include<map>
using namespace std;
long long h[10005];
long long n;
void swap(int x,int y)
{
    
    
	int t;
	t=h[x];
	h[x]=h[y];
	h[y]=t;
	return; 
}
void down(int i)
{
    
    
	int t,f=0;
	while (i*2<=n&&f==0)
	{
    
    
		if (h[i]>h[i*2]) t=i*2;
		else t=i;
		if (i*2+1<=n)
		{
    
    
			if (h[t]>h[i*2+1]) t=i*2+1;
		}
		if (t!=i)
		{
    
    
			swap(t,i);
			i=t;
		}
		else f=1;
	}
	return;
}
void jd()
{
    
    
	for (int i=n/2;i>=1;i--) down(i);
	return;
}
int zx()
{
    
    
	int t;
	t=h[1];
	h[1]=h[n];
	n--;
	down(1);
	return t;
}
void up(int p)
{
    
    
  while(p>1)
  {
    
    
    if(h[p]<h[p/2])
    {
    
    
      swap(h[p],h[p/2]);
      p/=2;
    }
    else break;
  }
}
void cr(int i)
{
    
    
	n++;
	h[n]=i;
	up(n);
	return;
}
int main()
{
    
    
	cin>>n;
	long long num=n,s=0;
	for (int i=1;i<=n;i++)
	{
    
    
		cin>>h[i];
	}
	jd();
	while (n>=2)
	{
    
    
		int t=zx(),t2=zx();
		s+=t+t2;
		cr(t+t2);
	}
	cout<<s;
	return 0;
}

Priority queue code:

#include<iostream>
#include<queue>
using namespace std;
priority_queue<long long> h;
long long n;
int main()
{
    
    
	cin>>n;
	long long s=0,x;
	for (int i=1;i<=n;i++)
	{
    
    
		cin>>x;
		h.push(-x);
	}
	while (n>=2)
	{
    
    
		int t=-h.top();
		h.pop();
		int t2=-h.top();
		h.pop();
		s+=t+t2;
		h.push(-t-t2);
		n--;
	}
	cout<<s;
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_49843717/article/details/115014758