糖 果 传 递

本文探讨了一个问题:如何在n个小朋友围成一圈,每个人初始糖果数量不等的情况下,通过最少的代价使所有人的糖果均等。作者提出了贪心算法策略,通过排序和单向传递优化糖果分配,揭示了如何利用货场选址问题的思想解决此问题。
摘要由CSDN通过智能技术生成

题目:

有 n 个小朋友坐成一圈,每人有 a[i]个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为 1。求使所有人获得均等糖果的最小代价。

输入格式

第一行输入一个正整数 n,表示小朋友的个数。接下来 n行,每行一个整数 a[i],表示第 i个小朋友初始得到的糖果的颗数。

输出格式

输出一个整数,表示最小代价。

数据范围

1≤n≤1000000,

0≤a[i]≤2×109,

数据保证一定有解。

输入样例

4
1
2
5
4

输出样例:

4

分析:

        首先分析用什么算法,我第一想到的是二分,但是想了一下后发现如果将糖果传递数作为二分标准,根本没法写(或者说我写不出来),再就是dfs,如果我们将每个点的状态都遍历一遍行不行呢?算一下时间复杂度,每一个点有2种情况,2个点就有2*2种情况,那么如果有1e6个点的话,时间复杂度就是o(2^{1000000}),时间复杂度太高了,舍弃;最后就是考虑贪心,将每个点都考虑一遍,时间复杂度是o(n),是可以接受的。

        如何进行贪心,首先确定什么是最好的情况,那就是点与点的交换只是单向的,如图1

 

想想看如果2个点中有平行边,那是不是相当于小朋友A把糖给小朋友B,然后B又把糖给A了呢。

        现在开始找规律。见图2

                                                                        图二

(不懂的话可以去看下货场选址问题)

代码:

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1000010;
typedef long long ll;

ll res, mid;
int a[N], p[N];

int main(){
    int n;
    cin >> n;

    for(int i = 1; i <= n; i ++){
        scanf("%d", &a[i]);
        mid += a[i];
    }

    mid /= n;

    for(int i = 2;i <= n ; i ++){
        p[i] = p[i - 1] + mid - a[i];
    }

    int x1 = 0;
    sort(p + 1, p + 1 + n);
    if(n % 2 == 0)x1 = (p[n / 2] + p[n / 2 + 1]) / 2;
    else x1 = p[n / 2 + 1];

    for(int i = 1;i <= n; i ++){
        res += abs(p[i] - x1);
    }
    cout << res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值