关于 糖果传递 一题的思路+代码

题目来源:AcWing 122.糖果传递

题目描述

有n个小朋友坐成一圈,每人有a[i]个糖果。
每人只能给左右两人传递糖果。
每人每次传递一个糖果代价为1。
求使所有人获得均等糖果的最小代价。

输入描述

第一行输入一个正整数n,表示小朋友的个数。
接下来n行,每行一个整数a[i],表示第i个小朋友初始得到的糖果的颗数。

输出描述

输出一个整数,表示最小代价。

数据范围

1 ≤ n ≤ 1000000,
0 ≤ a[ i ] ≤ 2×109,
数据保证一定有解。

输入样例

4
1
2
5
4

输出样例

4

OP

这道题代码不难,主要是思路,通过数学方法转化问题。

思路

我们假设第 i 名小朋友有 a[ i ] 颗糖,并向其右侧小朋友传递 x[ i ] 颗糖( x[ i ] 为整数,若为负值即说明反向传递)。( x[ n ] 也可以视作 x[ 0 ] )

在这种假设下,我们的所求即为 x[1]+x[2]+...+x[n1]+x[n]| x[ 1 ] | + | x[ 2 ] | + ... + | x[ n - 1 ] | + | x[ n ] | 的最小值。

设传递之后,每名小朋友均有 p 颗糖,我们可以列出如下方程组:

a[1]x[1]+x[n]=ba[ 1 ] - x[ 1 ] + x[ n ] = b
a[2]x[2]+x[1]=ba[ 2 ] - x[ 2 ] + x[ 1 ] = b

a[n1]x[n1]+x[n]=ba[ n - 1 ] - x[ n - 1 ] + x[ n ] = b
a[n]x[n]+x[n1]=ba[ n ] - x[ n ] + x[ n - 1 ] = b

整理①式,我们可以得出:x[1]=x[n]b+a[1]x[ 1 ] = x[ n ] - b + a[ 1 ]
将其代入②式,便可以得出x[2]=x[n]2b+a[1]+a[2]x[ 2 ] = x[ n ] - 2 * b + a[ 1 ] + a[ 2 ]
以此类推:x[i]=x[n]ib+a[1]+a[2]+...+a[i]x[ i ] = x[ n ] - i * b + a[ 1 ] + a[ 2 ] + ... + a[ i ]

此时,我们所求即转化为
x[n]b+a[1]+x[n]2b+a[1]+a[2]+...+x[n1]=x[n](n1)b+a[1]+a[2]+...+a[n1]+x[n]=x[n]0b+a[1]+a[2]+...+a[n]| x[ n ] - b + a[ 1 ] | + | x[ n ] - 2 * b + a[ 1 ] + a[ 2 ] | + ... + | x[ n - 1 ] = x[ n ] - ( n - 1 ) * b + a[ 1 ] + a[ 2 ] + ... + a[ n - 1 ] | + | x[ n ] = x[ n ] - 0 * b + a[ 1 ] + a[ 2 ] + ... + a[ n ] |
的最小值。

现在,我们就可以将上式看作另一个问题:
数轴上有一系列点: b+a[1],2b+a[1]+a[2],(n1)b+a[1]+a[2]+...+a[n1],0b+a[1]+a[2]+...+a[n]b + a[ 1 ] , 2 * b + a[ 1 ] + a[ 2 ] , ( n - 1 ) * b + a[ 1 ] + a[ 2 ] + ... + a[ n - 1 ] , 0 * b + a[ 1 ] + a[ 2 ] + ... + a[ n ] ,求某一点(x[ 0 ])与他们所有点的距离之和最短。

将 x[ 0 ] 放在这一系列点的中位数处显然是最短的,就如货仓选址这道题。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
using namespace std;

int main()
{
static long long n,a[1000006]={0},d[1000006],i,p;
cin>>n;
for(i=1;i<=n;i++){scanf("%lld",&a[i]);d[i]=a[i]+d[i-1];}
p=d[n]/n;
for(i=1;i<=n;i++)
{
d[i]-=i*p;
}
sort(d+1,d+1+n);
long long sum=0;
for(i=1;i<=n;i++)
{sum+=abs(d[i]-d[(n+1)/2]);}//与中位数距离
printf("%lld",sum);
return 0;
}

ED

y总yyds


关于 糖果传递 一题的思路+代码
https://tanyuu.github.io/2021.01-06/关于 糖果传递 一题的思路+代码/
作者
F Juny
发布于
2021年2月4日
许可协议