UVa11300

题目名称:Spreading the Wealth

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2275

 F. Spreading the Wealth 

Problem

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.

The Input

There is a number of inputs. Each input begins with n(n<1000001), 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.

The 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


题目大意:有 n 个人围成一个圈,每个人都有一些金币,每个人可以给他左右的人一些金币,问都拥有相同金币时需要转手多少金币


思路:这道题刚看时,丫的一点思路都没有。如果有编号为 1,2,3,4 四个人,如果 1 给 2 三个金币,2 给 1 五个金币,这相当于 2 给 1 两个金币,1 没给 2,所以可以设 s2 表示 2 给 1 的金币数。。。注意 s1 是表示 1 给 4 的金币数,设编号为 1 的人初始金币为 a1,他给 4 s1个金币,2 给他 s2 个金币,即后来的金币数为 M = a1 - s1 + s2,同理 M = a2 - s2 + s3...

第一个人: s2 = M - a1 + s1 = s1 - c1  (设c1=a1-M,下同)

第二个人: s3 = M - a2 + s2 = 2M - a1 - a2 + s1 = s1 - c2

第三个人 :s4 = M - a3 + s3 = 3M - a1 - a2 - a3 + s1 = s1 - c3

...

我们希望所有 s 值的和最小,即 |s1| + |s1-c1| + |s1-c2| + |s1-c3| +...我们可以看到 |s1-ci| 不就是从几何上表示 s1 到 ci 的距离么??所以 s1 的最优解就是这些数 ci 的中位数(自己动手画下图,移动下点可以看出,如果s1在c1处,向右移动,左边的距离加的比右边距离减少的少,说明向右移变小,同理,左移也一样,所以选中位数最小)


代码如下:

<span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
long long n,a[1000005],c[1000005];
int main()
{
    while(~scanf("%d",&n))
    {
        long long sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        long long m=sum/n;
        c[0]=0;
        for(int i=1;i<n;i++)
            c[i]=c[i-1]+a[i]-m;
        sort(c,c+n);
        long long x=c[n/2],tot=0;
        for(int i=0;i<n;i++)
            tot+=abs(x-c[i]);
        printf("%lld\n",tot);
    }
    return 0;
}</span>



posted @ 2015-05-27 23:30  maplefighting  阅读(93)  评论(0编辑  收藏  举报