第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個點,找出一個點到各點距離和最小。所以這個點就是中位數。
在這裏插入圖片描述

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#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;
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章