您的位置:首页 > 其它

cdoj 1018 王之新学期

2014-12-06 19:42 211 查看
新的学期到来了,王早已经把整个学期全都安排好了。

整个学期一共n天,第i天安排了Pi件事情。可是就在开学的前一天晚上,王突然觉得这个整个学期安排可能不够有趣。

一个学期是有趣当且仅当对于任意一个整数i(1≤i≤n),第i天的的事情数目总是等于倒数第i天的事情数目。

因此王必须花费一定代价改变安排使得整个学期变得有趣。

王每次操作都花费一个代价,可以将一件事情从当天提前到昨天或者延后到明天。(第一天的事情不能提前,最后一天的事情不能延后)

请问王最小要花费多少的代价使得一个学期是有趣的?

比如,当 n=3,p1=2,p2=2,p3=0
时,

王可以先花费一个代价将第一天的一件事延后到第二天,就变成了 p1=1,p2=3,p3=0。

再花费一个代价将第二天的一件事延后到第三天,就变成了 p1=1,p2=2,p3=1。

显然,p1=1,p2=2,p3=1是有趣的一个学期。花费的最小代价是2。

Input

一个整数T,表示数据组数。(T<1000)

接下来2×T行。每组数据两行。

第一行一个整数n,表示盒子的个数。(n<10000)

第二行n个整数,第i个整数Pi表示第i个天的最初的事件数。(ai<10000)

Output

每组数据输出一个整数。表示王花费的最少代价。(如果王无论如何都不能达到目的,则输出
-1


Sample input and output

Sample InputSample Output
3
2
0 1
3
1 3 2
5
1 0 0 0 0

-1
1
2

解析

贪心,从两边往中间堆。每次比较对称的两个点,取小的那个作为基准。多出来部分往中间堆。

从首尾两边往中间扫,先比较第一个和最后一个,把多出来的事移到第二个(正数或者倒数),直到扫到中间。再特殊处理n的奇偶情况就可以了。

#include<cstdio>

using namespace std;

#define LOCAL

typedef long long LL;

LL N,P[10010];

void readdata()
{
scanf("%lld",&N);
LL sum=0;
for(int i=1;i<=N;i++) scanf("%lld",&P[i]),sum+=P[i];
if(!(N&1) && (sum&1)) {printf("-1\n");return;}

LL ans=0; LL d;
for(int i=1;i<=N>>1;i++)
if(P[i]!=P[N-i+1])
if(P[i]>P[N-i+1])
{
d=P[i]-P[N-i+1];
P[i]-=d;
P[i+1]+=d;
ans+=d;
}
else
{
d=P[N-i+1]-P[i];
P[N-i+1]-=d;
P[N-i]+=d;
ans+=d;
}
printf("%lld\n",(N&1)?ans:ans-d/2);
}

int main()
{
#ifdef LOCAL
freopen("D.in","r",stdin);
#endif
int T; scanf("%d",&T);
for(int i=1;i<=T;i++)
readdata();
#ifdef LOCAL
while(1);
#endif
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: