UESTC 1018 王之新学期 贪心法

王之新学期

Time Limit: 5000/2000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit  Status

新的学期到来了,王早已经把整个学期全都安排好了。

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

一个学期是有趣当且仅当对于任意一个整数 i(1in)     ,第 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 Input Sample Output
3
2
0 1
3
1 3 2
5
1 0 0 0 0
-1
1
2

My Solution

关键是对奇偶讨论,中间位置,  以及迭代停止的位置,和额外讨论的地方
贪心策略:从两边开始历遍,把多余的任务往里移。
然后,偶则特殊处理中间两位,奇则只注意中间位置的数组下标(中间一个不用遍历到)及停下的时候的状态。
且如果n%2==0,则sum必须为偶。先行判断这个,如果不符合则直接输出-1,只有这个时候是-1,然后下面对于n%2==0,就一定存在了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
//#define LOCAL
const int maxn=10000+5;
int hz[maxn];
using namespace std;

int main()
{
    #ifdef LOCAL
    freopen("a.txt","r",stdin);
    #endif // LOCAL
    int T,n,sum,cot,tem;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(hz,0,sizeof(hz));sum=0;cot=0;
        for(int i=0;i<n;i++){
            scanf("%d",&hz[i]);
            sum+=hz[i];
        }
        if(n%2==0&&sum%2!=0) printf("-1");
        else{
            if(n%2==0){
                for(int i=0;i<(n/2-1);i++){    //最后一步不能再这么移了,中间,看看是不是和为偶数
                    cot+=abs(hz[i]-hz[n-i-1]);//cout<<hz[i]<<" ";
                    if(hz[i]>=hz[n-i-1]) hz[i+1]+=hz[i]-hz[n-i-1];
                    else hz[n-i-1-1]+=hz[n-i-1]-hz[i];
                }
                tem=hz[n/2-1]+hz[n/2];cout<<cot+abs(tem/2-hz[n/2]);//如n=4,0 1 2 3 用下面的会输出0,n=2,0 2也是输出0;
                //printf("%d",cot+abs(tem/2-hz[n/2]));//<<cot+abs(tem/2-hz[n/2])不能用printf()输出,有类型的错误转化
                //arning: format '%d' expects argument of type 'int', 
                //but argument 2 has type '__gnu_cxx::__enable_if<true, double>::__type {aka double}' [-Wformat=]
            }
            else{
                for(int i=0;i<(n-1)/2;i++){
                    cot+=abs(hz[i]-hz[n-i-1]);
                    if(hz[i]>=hz[n-i-1]) hz[i+1]+=hz[i]-hz[n-i-1];
                    else hz[n-i-1-1]+=hz[n-i-1]-hz[i];
                }
                printf("%d",cot);
            }
        }
        if(T) printf("\n");
    }
    return 0;
}

谢谢

你可能感兴趣的:(字符串,ACM,ICPC,OJ,uestc,贪心法)