糖果传递(数学)

这道题本质上是一个数学题,先设xi为最优情况下第i个小朋友给第i-1个小朋友的糖果数(xi为负数代表是第i-1个小朋友给了第i个小朋友糖果),特殊情况:当i为1时,默认i-1=n,也就是x1表示第1个小朋友给第n个小朋友的糖果数。那我们的结果就是所有xi的绝对值的和了(传递糖果的个数即为最终代价),题目中已经给出每个小朋友一开始所拥有的糖果数ai,设每个小朋友最终取得的糖果数为mid,那么第i个小朋友最终的糖果数mid取决于一开始所具有的糖果数ai和他给第第i-1个小朋友的糖果数xi以及第i+1个小朋友给他的糖果数xi+1,也就是mid=ai-xi+x(i+1),化简得x(i+1)-xi=mid-ai,由这个式子可得

(1)  x2-x1=mid-a1

(2)  x3-x2=mid-a2

……

(n-1)  xn-x(n-1)=mid-a(n-1)

对上述式子进行合并整理得

(1)+(2)得x3-x1=2*mid-(a2+a1)

(1)+(2)+(3)得x4-x1=3*mid-(a3+a2+a1)

……

(1)+(2)+……+(n-1)得xn-x1=(n-1)*mid-(a(n-1)+a(n-2)+……+a1)

对合并后的式子进行移项得:

x2=x1-(a1-mid)

x3=x1-((a2+a1)-2*mid)

x4=x1-((a3+a2+a1)-3*mid)

……

xn=x1-((a(n-1)+……+a2+a1)-(n-1)*mid)

又因为x1=x1-0

我们最终结果是xi的绝对值的和,看到上面移项后的式子容易想到距离公式,从而我们的结果就是一个点到0,(a1-mid),((a2+a1)-2*mid),……,((a(n-1)+……+a2+a1)-(n-1)*mid)这些点的距离和的最小值,这我们就可以转化为货仓选址问题了,直接取一个中位数进行计算即可,下面是代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1000003;
long long a[N],s[N];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		s[i]=s[i-1]+a[i];
	}
	long long mid=s[n]/n;
	for(int i=1;i<=n;i++)
		s[i]-=i*mid;
	sort(s,s+n);
	long long ans=0;
	for(int i=0;i<n;i++)
		ans+=abs(s[i]-s[n/2]);
	printf("%lld",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值