HDU5353 Average

Problem Description
There are  n  soda sitting around a round table. soda are numbered from  1  to  n  and  i -th soda is adjacent to  (i+1) -th soda,  1 -st soda is adjacent to  n -th soda.

Each soda has some candies in their hand. And they want to make the number of candies the same by doing some taking and giving operations. More specifically, every two adjacent soda  x  and  y  can do one of the following operations only once:
1.  x -th soda gives  y -th soda a candy if he has one;
2.  y -th soda gives  x -th soda a candy if he has one;
3. they just do nothing.

Now you are to determine whether it is possible and give a sequence of operations.


题目大意:N个人围成一圈,每个人可以给左边或右边最多1个糖果,相邻两个人最多有一次糖果的传递(a给b一个,b不能再给a)


思路:N个人中最多的一定会向外给(除非所有人一样多),假如他给了左边一个,那么左边的那个人就只能和再左的人给/拿糖果,进行操作之后如果和最后的平均数不一致,那么这个这种方式错误,再令第一个人给右边一个,然后进行相同的操作。这样对数组按顺时针和逆时针分辨判断一次即可。

可能有这种特例,按第一个顺序处理时,某个人可能和他左边的人没有操作,那么说明这个人的糖果数 = 平均值,下一个人也就不可能和他再进行操作,所以操作的方向不会改变。


注意计算平均值时考虑不能整除的情况。



#include<cstdio>

using namespace std;


 const int SIZE = 100005;
 int a1[SIZE];
 int a2[SIZE];
 int N,ave;

 int ans[SIZE][2];
 int no = 0;

 int left(int p){
    p--;
    if(p < 0) p = N - 1;
    return p;
}

 int right(int p){
    p++;
    return p % N;
}

int main() {
    // TODO Auto-generated method stub
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        long long sum = 0;
        int max = -1;
        int pos = 0;
        for(int i=0;i<N;i++){
            scanf("%d",&a1[i]);
            a2[i] = a1[i];
            if(a1[i] > max){
                max = a1[i];
                pos = i;
            }
            sum += a1[i];
        }
        long long ln = N;
        if(sum%ln != 0){
            printf("NO\n");
            continue;
        }
        ave = (int)(sum / ln);

        if(a1[pos] - ave > 2 || a1[pos] - ave < -2){
            printf("NO\n");
            continue;
        }

        bool flag = true;

        no = 0;
        int p = pos, next = left(p);
        for(int i=1;i<=N;i++){
            if(a1[p] > ave){
                a1[p]--;
                a1[next]++;
                ans[no][0] = p + 1;
                ans[no++][1] = next + 1;
            }
            else if(a1[p] < ave){
                a1[p]++;
                a1[next]--;
                if(a1[next]<0){
                    flag = false;
                    break;
                }
                ans[no][0] = next + 1;
                ans[no++][1] = p + 1;
            }
            if(i>1 && a1[p]!=ave){
                flag = false;
                break;
            }
            p = next;
            next = left(next);
        }

        if(flag){
            printf("YES\n");
            printf("%d\n",no);
            if(no != 0){
                for(int i=0;i<no;i++) printf("%d %d\n",ans[i][0],ans[i][1]);;
            }
            continue;
        }

        flag = true;
        no = 0;
        p = pos;
        next = right(p);
        for(int i=1;i<=N;i++){
            if(a2[p] > ave){
                a2[p]--;
                a2[next]++;
                ans[no][0] = p + 1;
                ans[no++][1] = next + 1;
            }
            else if(a2[p] < ave){
                a2[p]++;
                a2[next]--;
                if(a2[next]<0){
                    flag = false;
                    break;
                }
                ans[no][0] = next + 1;
                ans[no++][1] = p + 1;
            }
            if(i>1 && a2[p]!=ave){
                flag = false;
                break;
            }
            p = next;
            next = right(next);
        }

        if(flag){
            printf("YES\n");
            printf("%d\n",no);
            if(no != 0){
                for(int i=0;i<no;i++) printf("%d %d\n",ans[i][0],ans[i][1]);;
            }
        }
        else{
            printf("NO\n");
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值