HDU 5350(MZL's munhaff function-哈夫曼树)

MZL's munhaff function

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 230    Accepted Submission(s): 133


Problem Description
MZL is a mysterious mathematician, and he proposed a mysterious function at his young age.
Stilwell is very confused about this function, and he need your help.
First of all, given n positive integers Ai and AiAi+1 .
Then, generate n positive integers Bi
Bi=j=inAj

Define f(i,j) for i,jZ
f(i,j)=0min(f(i1,j+1),f(i,j2)+Bi)1011037(i,j)=(1,1)i,j[1,n], (i,j)(1,1)otherwise

Find f(n,1) .
 

Input
The first line of the input contains a single number T , the number of test cases.
For each test case, the first line contains a positive integer n , and the next line contains n positive integers Ai .
T100 , 1n105 , n106 , 1Ai104 .
 

Output
For each test case, output f(n,1) in a line.
 

Sample Input
  
  
3 3 1 1 1 5 28 26 25 24 1 10 996 901 413 331 259 241 226 209 139 49
 

Sample Output
  
  
5 233 11037
Hint
case 1 : f(1,1)=0 f(1,2)=f(1,1)+3=3 f(1,3)=f(1,2)+3=6 f(2,1)=min(f(2,1)+2,f(1,2))=3 f(2,2)=min(f(2,1)+2,f(1,3))=5 f(2,3)=f(2,2)+2=7 f(3,1)=min(f(3,1)+1,f(2,2))=5
 

Author
SXYZ
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5421  5420  5419  5418  5417 
 

哈夫曼树

解决如下问题:有一堆数,每次拿2个数,换成它们的和,代价是它们的和,求把数变为1个的最小花费

显然每次取当前最小(构建哈夫曼树)

考虑本题,f[i][j] 表示拿了 前Ai个数,当前最后那层有j个空的叶节点

我们可以拿一个数去填空点,不需要代价f[i+1][j-1] 

也可以把叶子节点上有数往下画一层 f[i][2j] 代价就是上面所有取的数 Bi 








#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (1000000+10)
#define MAXAi (10000+10)
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int n;
ll a[MAXN];
priority_queue<ll,vector<ll> , greater<ll> > q;
int main()
{
//	freopen("H.in","r",stdin);
	
	int T;cin>>T;
	while (T--) {
		cin>>n;
		For(i,n) 
		{
			scanf("%lld",&a[i]);q.push(a[i]);
		}
//		
//		if (n==1) {
//			puts("0");continue;
//		}
		ll ans=0;
		while (q.size()>=2)
		{
			ll val=q.top(); q.pop();
			val+=q.top(); q.pop();
			ans+=val;
			q.push(val);
		}
		
		cout<<ans<<endl;
		while (!q.empty()) q.pop();
		
		
	}
	
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值