HDU-5353-Average

原题
There are nn soda sitting around a round table. soda are numbered from 11 to nn and ii-th soda is adjacent to (i+1)(i+1)-th soda, 11-st soda is adjacent to nn-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 xx and yy can do one of the following operations only once:

  1. xx-th soda gives yy-th soda a candy if he has one;
  2. yy-th soda gives xx-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.
Input
There are multiple test cases. The first line of input contains an integer TT, indicating the number of test cases. For each test case:

The first contains an integer nn (1≤n≤105)(1≤n≤105), the number of soda.
The next line contains nn integers a1,a2,…,ana1,a2,…,an (0≤ai≤109)(0≤ai≤109), where aiai denotes the candy ii-th soda has.
Output
For each test case, output “YES” (without the quotes) if possible, otherwise output “NO” (without the quotes) in the first line. If possible, then the output an integer mm (0≤m≤n)(0≤m≤n) in the second line denoting the number of operations needed. Then each of the following mm lines contain two integers xx and yy (1≤x,y≤n)(1≤x,y≤n), which means that xx-th soda gives yy-th soda a candy.
Sample Input
3
6
1 0 1 0 0 0
5
1 1 1 1 1
3
1 2 3
Sample Output
NO
YES
0
YES
2
2 1
3 2
题意:
有n个人围成一圈,每个人都有ai颗糖,每个人都可以与相邻的两个人之间进行一次操作:要么a给a+1要么a+1给a要么不给。问最后能否使所有人手上的糖一样多。
题解:
这道题目有特判所以只要最后结果对就可以。我们可以遍历所有人,判断是否会操作,注意如果a与b之间进行两次操作相当于没有操作。之间可以适当剪枝,如果均值不为整型则肯定不能均分。
期间可以用op数组来记录第i个人与前后两个人之间的操作。更多细节见代码。
(还有就是这道题目用c输入输出会好过一些,c++输入输出流可能会超时)
附上AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int op[100005][2], a[100005];//op数组用来记录两人之间是否进行操作,第二维中0代表给下一个人糖,1代表给上一个人糖
int t,n,judge,x,y,cnt;//judge用来记录是否能够均分,cnt用来记录操作次数
long long int sum;
int main()
{
    scanf("%d",&t);//cin>>t;
    while(t--)
    {
        scanf("%d",&n);//cin>>n;
        sum=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);//cin>>a[i];
            sum+=a[i];
        }
        judge=1;
        if(sum%n)judge=0;//如果均值不为整数则不能均分
        if(judge)
        {
            for(int i=0;i<n;i++)
                a[i]-=(sum/n);//使每一个数都在0左右,最终若是都是0则表示能均分
            memset(op,0,sizeof(op));//初始化
            for(int i=0;i<2*n;i++)
            {
                x=i%n;
                y=(i+1)%n;//第i个人与第i+1个人之间的操作
                if(a[x]>0&&a[y]<=0&&!op[x][0])//第i个给第i+1个人糖
                {
                    a[x]--;
                    a[y]++;
                    if(!op[y][1])op[x][0]=1;//如果第i+1个人没有和第i个人进行操作则标记第i个人与第i+1个人之间进行操作
                    else op[x][0]=op[y][1]=0;//如果两人之间进行了两次操作,则相当于没有进行操作
                }
                else if(a[x]<0&&a[y]>=0&&!op[y][1])//第i+1个人给第i个人糖
                {
                    a[x]++;
                    a[y]--;
                    if(!op[x][0]) op[y][1]=1;//与上相同
                    else op[x][0]=op[y][1]=0;
                }
            }
            cnt=0;
            for(int i=0;i<n;i++)
            {
                if(a[i]!=0)//如果不都为0,则表示不能均分
                {
                    judge=0;
                    break;
                }
                cnt+=(op[i][0]+op[i][1]);//记录操作数
            }
            if(n==1) judge=1;//如果只有一个人则一定能均分
            if(n==2&&cnt==2) judge=0;//有两个人还进行了两次操作,则证明一定是不能均分的
        }
        if(judge)//如果可以均分
        {
            printf("YES\n%d\n",cnt);//cout<<"YES"<<endl;
            //cout<<cnt<<endl;
            for(int i=1;i<=n;i++)
            {
                if(op[i-1][0]==1)
                {
                    x=i+1;//给后边的那个人糖
                    if(i==n) x = 1;
                    printf("%d %d\n",i,x);//cout<<i<<" "<<x<<endl;
                }
                if(op[i-1][1]==1)
                {
                    x=i-1;//给欠扁的人糖
                    if(i-1==0)x=n;
                    printf("%d %d\n",i,x);//cout<<i<<" "<<x<<endl;
                }
            }
        }
        else printf("NO\n");//cout<<"NO"<<endl;
    }
    return 0;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/83052262
今日推荐