0
点赞
收藏
分享

微信扫一扫

【寒假算法题练习】1.8

zhyuzh3d 2022-01-09 阅读 36

寒假算法题练习1.8

题目

题目描述:
原题来自:HAOI 2008

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

输入格式:
第一行有一个整数 n ,表示小朋友个数;
在接下来 n行中,每行一个整数 ai。

输出格式:
输出使所有人获得均等糖果的最小代价。

样例:
输入数据 1:
4
1
2
5
4
输出数据 1:
4

数据范围与提示:
对于 30% 的数据,n≤1000;
对于 100% 的数据,n≤10^6,保证答案可以用 64位有符号整数存储。

分析

保证答案可以用 64位有符号整数存储:使用long long型存储
每人只能给左右两人传递糖果:看做单向传递,传递个数可为正负数

a[i]:第i个小朋友原来拥有的糖果数
s[i]:第i个小朋友给第i+1个小朋友的糖果数
(因为围成圈,所以s[n]是第n个小朋友给第1个小朋友的糖果数)
在这里插入图片描述

由图中糖果给予关系知:给下一个人糖果数=自己原本拥有糖果数+上一个小朋友给自己的糖果数-均等糖果数
s[i]=a[i]+s[i-1]-avg;
则:
s[1]=s[1]-c[1] (c[1]=0)
s[2]=a[2]+s[1]-avg=s[1]-c[2] (c[2]=avg-a[2])
s[3]=a[3]+s[2]-avg=s[1]-c[3] (c[3]=2×avg-a[2]-a[3]=c[2]+avg-a3)
……
s[n]=a[n]+s[n-1]-avg=s[1]-c[n] (c[n]=n×avg-a[2]-a[3]-…-a[n]=c[n-1]+avg-a[n])
要求的最小代价即min{s[1]+……+s[n]},则转化为s[1]到c[i]的距离之和,所以s[1]为c[1]~c[n]的中位数

代码

#include <iostream>
#include<algorithm>

using namespace std;
long long i,n,weight=0,sum=0,avg, a[1000001],s[1000001],c[1000001];
int main()
{
    cin>>n;//读入
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];//求和
    }
    avg=sum/n;//平均数
    c[1]=0;
    for(i=2;i<=n;i++)
    {
        c[i]=c[i-1]+avg-a[i];//c[i]的关系由上面等式得到
    }
    sort(c+1,c+n+1);//对c[i]排序
    s[1]=c[n/2+1];//c[i]的中位数
    for(i=1;i<=n;i++)
    {
        weight+=abs(s[1]-c[i]);//求s[1]到c[i]的距离之和
    }
    cout<<weight;//输出最小权重
}

举报

相关推荐

0 条评论