第1部分 基础算法(提高篇)--第1章 贪心算法-1432:糖果传递

1432:糖果传递

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 999 通过数: 452
【题目描述】
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。

【输入】
第一行一个正整数n≤1000000,表示小朋友的个数.

接下来n行,每行一个整数ai,表示第i个小朋友得到的糖果的颗数.

【输出】
求使所有人获得均等糖果的最小代价。

【输入样例】
4
1
2
5
4
【输出样例】
4


思路:
最终每个小朋友的糖果数等于平均数,假设编号为i的小朋友开始有Ai个糖果。Xi表示第i个小朋友给了第i-1个小朋友Xi个糖果,Xi<0表示第i-1个小朋友给了第i个小朋友|Xi|个糖果。则最终的答案ans=|X1|+|X2|+……+|Xn|。
对于第一个小朋友,他给了第n个小朋友X1个糖果,得到第2个小朋友的X2个糖果,最终还剩A1-X1+X2个糖果,即ave个糖果,所以得到方程A1-X1+X2=ave。所以ans=|X1|+|X1-C1|+|X1-C2|+…+|X1-Cn-1|,要使ans尽可能小。因为|X1-Ci|的几何意义是数轴上点X1到Ci的距离,所以问题转化为:给定数轴上n个点,找出一个点到各点距离和最小。所以这个点就是中位数。
第1部分 基础算法(提高篇)--第1章 贪心算法-1432:糖果传递_第1张图片

#include
#include
#include
#include
#include
#define LL long long
using namespace std;
const int N=1000005;
int n,ave;
int a[N],f[N];
LL sum,ans;
int main(){
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
        scanf("%d",&a[i]);
        sum += a[i];
    }
    ave=sum/n; //最终小朋友手里的糖数 
    for(int i = 2;i <= n;i++)f[i] = f[i-1] + a[i-1]-ave; //左边的小朋友传给右边
    sort(f+1,f+n+1);
    int mid = n/2+1;//传递的中位数 
    for(int i=1;i<=n;i++)  
    for(int i = 1;i <= n;i++){
        ans += abs(f[i]-f[mid]);//只需要传递到中位数就好了,多了太浪费
    }
    printf("%lld\n",ans);
    return 0;
}
 

你可能感兴趣的:(信息学C++,一本通)