Description
有一棵无穷大的满二叉树,根为star,其余所有点的权值为点到根的距离,如图:
现在你有一些扑克牌,点数从1到13,你要把这些扑克牌全部放到这个树上:
1. 当你把点数为i的扑克牌放在权值为j的点上,那么你会得到i*j的分数。
2. 当你把一个扑克牌放在一个节点上,那么你就不能把别的扑克牌放在这个节点以及这个节点的子树上。
你的目标是最小化你的得分。
Input
文件名为 poker.in
输入第一行为一个数字N,表示你有的扑克牌数;
接下来一行N个数字,数字在1到13之间。
Output
文件名为 poker.out
一个数字,最小得分。
Sample Input
3
5 10 13
Sample Output
43
Data Constraint
Hint
【样例说明】
【数据范围】
30%数据 N<=100
100%数据满足1<=N<=10000.
.
.
.
.
.
.
分析
这题听别人讲与哈夫曼树有关
但简化一下
就会发现
这题其实就是类似于
合并果子
.
.
.
.
.
程序:
#include<iostream>
using namespace std;
int n;
long long a[10001];
void kp(int l,int r)
{
int i,j;
long long min,g;
if (l>=r) return;
i=l;j=r;min=a[(l+r)/2];
do
{
while (a[i]<min) i++;
while (a[j]>min) j--;
if (i<=j)
{
g=a[i];a[i]=a[j];a[j]=g;
i++;j--;
}
}
while (i<=j);
kp(l,j);
kp(i,r);
}
int main()
{
int ans,bb,k;
cin>>n;
a[n+1]=2147483647;
for (int i=1;i<=n;i++)
cin>>a[i];
kp(1,n);
ans=0;
for (int i=2;i<=n-1;i++)
{
a[i]=a[i]+a[i-1];
ans=ans+a[i];
for (int j=i+1;j<=n+1;j++)
if (a[i]<a[j]&&a[i]>=a[j-1])
{
bb=j-1;
break;
}
k=a[i];
for (int j=i;j<=bb-1;j++)
a[j]=a[j+1];
a[bb]=k;
}
cout<<ans+a[n-1]+a[n];
return 0;
}