码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 11300 Spreading the Wealth

时间:2018-11-18 14:15:10      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:while   cpp   method   eal   desc   ble   des   sid   NPU   

Description

A Communist regime is trying to redistribute wealth in a village. They have have decided to sit everyone around a circular table. First, everyone has converted all of their properties to coins of equal value, such that the total number of coins is divisible by the number of people in the village. Finally, each person gives a number of coins to the person on his right and a number coins to the person on his left, such that in the end, everyone has the same number of coins. Given the number of coins of each person, compute the minimum number of coins that must be transferred using this method so that everyone has the same number of coins.

Input

There is a number of inputs. Each input begins with \(n (n \le 1000000)\), the number of people in the village. \(n\) lines follow, giving the number of coins of each person in the village, in counterclockwise order around the table. The total number of coins will fit inside an unsigned 64 bit integer.

Output

For each input, output the minimum number of coins that must be transferred on a single line.

Sample Input

3
100
100
100
4
1
2
5
4

Sample Output

0
4

Solution

考虑相邻的两个人\(A\)\(B\),或者\(A\)\(B\)金币,或者\(B\)\(A\)金币,所以设\(x_{i}\)为第\(i\)个人给第\(i - 1\)个人的金币数量(\(x_{1}\)为第\(1\)个人给第\(n\)个人的金币数量),\(x_{i} \ge 0\)表示第\(i\)个人给第\(i - 1\)个人金币,\(x_{i} \lt 0\)表示第\(i-1\)个人给第\(i\)个人金币,\(c = \frac{\sum_{i=1}^{n}a_{i}}{n}\)为最终每个人手中的金币数量,由此我们可以得到方程组:
\[ \begin{align} a_{1} - x_{1} + x_{2} &= c\\a_{2} - x_{2} + x_{3} &= c\\\dots\\a_{n} - x_{n} + x_{1} &= c\\\end{align} \]
进一步可以得到:
\[ \begin{align} x_{2} &= x_{1} - \left(a_{1} - c\right)\\x_{3} &= x_{2} - \left(a_{2} - c\right) = x_{1} - \left(a_{1} - c\right) - (a_{2} - c)\\\dots\\x_{n} &= x_{1} - \left(a_{1} - c\right) - (a_{2} - c) - \cdots - (a_{n-1} - c)\\\end{align} \]
我们不妨令:
\[ \begin{align} d_{1} &= 0\\d_{2} &= \left(a_{1} - c\right)\\d_{3} &= \left(a_{1} - c\right) + \left(a_{2} - c\right)\\\dots\\d_{n} &= \left(a_{1} - c\right) + \left(a_{2} - c\right) + \cdots + \left(a_{n-1} - c\right)\\\end{align} \]

我们的目标是最小化\(\left|x_{1}\right| + \left|x_{2}\right| + \cdots \left|x_{n}\right|=\left|x_{1} - d_{1}\right| + \left|x_{1} - d_{2}\right| + \cdots \left|x_{1} - d_{n}\right|\),这相当于已知\(x\)轴上的\(n\)个点,我们要找到一个点\(x_{1}\),使得\(x_{1}\)到各个点的距离之和最小,不难证明,当\(x_{1}\)为这\(n\)个数中的中位数时,可以得到最优解。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000011;
ll a[maxn], d[maxn];
int main() {
  int n;
  while (scanf("%d", &n) == 1) {
    ll sum = 0;
    for (int i = 1; i <= n; ++i) {
      scanf("%lld", a + i);
      sum += a[i];
    }
    ll c = sum / (ll)n;
    for (int i = 1; i < n; ++i) {
      d[i] = d[i - 1] + a[i] - c;
    }
    d[n] = 0;
    sort(d + 1, d + 1 + n);
    int p = (n + 1) / 2;
    ll v = d[p], ans = 0;
    for (int i = 1; i < p; ++i)
      ans += v - d[i];
    for (int i = p + 1; i <= n; ++i)
      ans += d[i] - v;
    printf("%lld\n", ans);
  }
  return 0;
}

UVA 11300 Spreading the Wealth

标签:while   cpp   method   eal   desc   ble   des   sid   NPU   

原文地址:https://www.cnblogs.com/hitgxz/p/9977673.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!