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 }