UVa 11300 分金币

https://vjudge.net/problem/UVA-11300

题意:

圆桌上有n个人,每个人都有一定的初始金币,每个人可以给他旁边的人一些金币,最终使每个人的金币数相等。计算最少需要转手的金币数量。

思路:
考数学。首先计算出平均金币数M,设每个人一开始的金币数为Ai。

我们设xi代表第i号给第i-1号的金币数量(x1代表第1号给最后1号的金币数量)。(如果是负的就说明是获得)

于是,我们可以列式计算:

1号:A1+x2-x1=M   —>     x2=M-A1+x1

2号:A2+x3-x2=M   —>     x3=M-A2+x2

3号:A3+x4-x3=M   —>     x4=M-A3+x3

因为最终我们是要计算出xi的和,那么:

x2=x1-C1   (C1=A1-M,下面类似)

x3=x1-C2

x4=x1-C3

接下来就是计算|x1|+|x1-C1|+|x1-C2|+...+|x1-Cn-1|的最小值,这就相当于给定数轴上的n个点,找出一个到它们的距离之和尽量小的点,这个点就是中位数。

 1 #include<iostream> 
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 1000000 + 5;
 6 int n;
 7 long long a[maxn],c[maxn];
 8 
 9 int main()
10 {
11     ios::sync_with_stdio(false);
12     //freopen("D:\txt.txt", "r", stdin);
13     while (cin >> n)
14     {
15         long long sum = 0;
16         for (int i = 1; i <= n; i++)
17         {
18             cin >> a[i];
19             sum += a[i];
20         }
21         long long m = sum / n;
22         c[0] = 0;
23         for (int i = 1; i < n; i++)
24             c[i] = c[i - 1] + a[i] - m;
25         sort(c, c + n);
26         long long x1 = c[n / 2], ans = 0;
27         for (int i = 0; i < n; i++)
28             ans += abs(x1 - c[i]);
29         cout << ans << endl;
30     }
31 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6501536.html