有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
标签:rip ems ++ 代码 printf 开始 turn tchar tput
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
求使所有人获得均等糖果的最小代价。
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=1145
显然最后每个小朋友分到的糖数 s 是可以直接算的。。。
假设刚开始每个第 i 个小朋友有 k [ i ] 个糖。。第 i 个小朋友给第 i - 1 个小朋友 t [ i ] 个糖,第 n 个小朋友给第一个小朋友 t [ n ] 个糖。。
于是可以列出方程: k [ i ] - t [ i ] + t [ i + 1 ] = s
记 C [ i ] = ∑ ( k [ j ] - s ) (1 <= j <= i )
于是:
t [ 2 ] = s - k [ 1 ] + t [ 1 ] = t [ 1 ] - C [ 1 ]
t [ 3 ] = s - k [ 2 ] + t [ 2 ] = 2*s - k [ 2 ] - k [ 1 ] + t [ 1 ] = t [ 1 ] - C [ 2 ]
t [ 4 ] = t [ 1 ] - C [ 3 ]
。。。
我们要求的是 ∑ | t [ i ] - C [ i - 1 ] | ,实质上就是给出数轴上若干个点 C0 ,C1 ,C2 。。。。 然后求一个点 x 使得总距离最小。。。
显然用最中间的那个点是最优的。。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 1000050
#define LL long long
using namespace std;
inline int Read(){
int x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int n;
int k[N],t[N];
LL mid,ans,s;
int main(){
n=Read();
for(int i=1;i<=n;i++){
k[i]=Read();s+=k[i];
}
s=s/n;
for(int i=1;i<=n;i++)
t[i]=t[i-1]-k[i]+s;
sort(t+1,t+n+1);
mid=t[n/2];
for(int i=1;i<=n;i++)
ans+=abs(t[i]-mid);
printf("%lld\n",ans);
return 0;
}
This passage is made by Iscream-2001.
标签:rip ems ++ 代码 printf 开始 turn tchar tput
原文地址:http://www.cnblogs.com/Yuigahama/p/7784336.html