【算法设计与分析】分金币
算法2016-06-30
【题目】
【输入输出要求】
【输出样例】
【源代码】
<span style="font-family:Microsoft YaHei;font-size:24px;">//中位数问题
#include<stdio.h>
#include<algorithm>
int m[1000001],p[1000001];
int sub(int a,int b)
{
if(a < b)
{
return b - a;
}
else
{
return a - b;
}
}
int main()
{
long long int n,Min,t;
while(scanf("%lld",&n)!=EOF)//共n人
{
long long int s=0;
Min=0;
for(long long int i=0;i<n;i++)//输入每个人的金币数
{
scanf("%d",&m[i]);
s +=m[i];
}
t=s/n;//t为最终每人应该拿到的金币数
p[0]=0;
for(long long int i=1;i<n;i++)
{
p[i]=p[i-1]+m[i]-t;
}
std::sort(p,p+n);//进行从小到大排序
long long int x=p[n/2];//取中位数
for(long long int i=0;i<n;i++)//总转移的金币数目由每一个人与中位数的差的累积
Min+=sub(x,p[i]);
printf("%lld\n",Min);
}
return 0;
}</span>
m[i]-x[i]+x[i+1]=t,c[i]=m[i]-t; x[i+1]=t-m[i]+x[i]=t-m[i]+(t-m[i-1]+x[i-1])=...=x[1]-c[i+1];将问题转化,表示此时我已经求出每个人要转移的数目为xi
如何使得所有的xi的和最小,即是|x[1]-c[i]|的和最小,每一个|x[1]-c[i]|表示一个点与点之间的距离之和最小
那么问题转化为求中位数的问题
p[i]为|x1|,|x1-c1|,|x1-c2|,|x1-c3|,|x1-c4|,...,|x1-cn-1|中的ci值
找出一个点到各点距离之和最小