题目意思
圆桌旁坐着n个人,每个人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等,你的任务是求出被转手的金币数量的最小值。
这道题乍看没有什么思路,细看,也没有
这道题目看着挺复杂的,它的解析我看了三次都没有看下去,今天终于看完了;
根据题意可以这样想;假设有3个人,标号为1 2 3;
1号可以给2号或者3号金币,2号可以给3号或者1号金币,而3号可以给1号或者2号金币;
我们可以假设一个环形,
3号的金币由1号给出(可正可负可为零),2号的金币由3号给出,1号的金币由2号给出;
所以可以列出一个行列式;(M为最终平衡的状态)
A1-x1+x2=M;
A2-x2+x3=M;
A3-x3+x1=M;
我们可以理解看出就算x2大于A2,(就是指2号给1号的金币),它还可以由x3补给,A3一时拿不出x3也可以由x1加上(这里的x1,x2,x3均是可正可负可为零),
我们理想化的认为可以经过一轮交换达到平衡,虽然有可能不行,但是最终的形态就是这个样子,他需要的最终总会循环到他的手中。而且这样也包括了所有的交换,所以这样列式子是可以的,然后就是求解了;
这里我们用x1代替所有的变量
A1-x1+x2=M; ——x2=x1-A1+M;
因为A1和M均为常量,所以可以用同一个值来表示
(我们可以规定C1=A1-M),所以原式就变成了
x2=x1-c1; 下面同理
A2-x2+x3=M; ——x3=x2-A2+M;——x2=x1-C2;
A3-x3+x1=M;
由于最后一条得到的为x1=所以可以不用列式子;
所以最后就演变成了求
|x1|+|x1-C1|+|x1-C2|+|x1-C3|+……|x1-Cn-1|的最小值
从几何意义上来讲|x1-Ci| 就是数轴上点x1到Ci的距离。
所以题意就又演变成了:给定的n的点,找出一个到它们距离之和尽量小的点;能够理解,中位数离他们所有的点最小。
所以就是求中位数
代码如下
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#define ll long long
using namespace std;
#define N 1000010
ll a[N],c[N];
int main()
{
int t;
while(~scanf("%d",&t))
{
ll sum=0;
for(int i=1;i<=t;i++)
{
scanf("%lld",&a[i]);
sum+=a[i];
}
ll tot=sum/t;
memset(c,0,sizeof(c));
for(int i=1;i<t;i++)
{
c[i]=c[i-1]+a[i]-tot;
}
sort(c,c+t);
ll x1=c[t/2],ans=0;
for(int i=0;i<t;i++)
{
ans+=abs(x1-c[i]);
}
printf("%lld\n",ans);
}
return 0;
}