2015多校第6场 HDU 5353 Average 贪心,细节处理

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5353

题意:有n个人围城一个环,每一个人手里都有一些糖果,第i个人有ai块。现在有三种操作:第i个人给第i+1个人一块。第i+1个人给第i个人一块。什么都不做。第i个人和第i+1个人之间,可以选择一种操作并执行,问最终能不能让所有人手里的糖相等。

解法:贪心。

当n = 1 时,永远是YES

当n = 2 时,注意1和2之间只能有一种操作,不存在循环。

当n > 2 时:

糖的总数不能均分到n个人手中,直接NO

可以分开,存在一个循环,那么枚举第1个人对第2个人的操作,那么对于第2个人及以后的人来说它的左侧已经确定了,那么它为了维护自己的糖数是平均值,只能对下一个人进行操作,如果当前比平均值少1,那么从下一个人手里拿一个,如果正好,那么不操作,如果多一个,那么给下面的人一个,其他情况都是无解的。

注意:在操作时,要保证它当前有糖。所以要判断一下。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+6;
typedef long long LL;
int a[maxn], ans[maxn];

int main()
{
    int T, n;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        LL sum = 0, ave = 0;
        for(int i=0; i<n; i++){
            scanf("%d", &a[i]);
            sum += a[i];
        }
        bool flag = 1;
        int num;
        ave = sum/n;
        memset(ans, 0, sizeof(ans));
        if(sum%n){
            flag = 0;
        }
        else if(n == 2){
            if(abs(a[0]-ave) >= 2) flag = 0;
            else if(abs(a[0]-ave)){
                ans[0]=a[0]>a[1]?1:-1;
            }
        }
        else if(n>2){
            int i,j,k;
            for(i=-1; i<=1; i++){
                ans[0]=i;
                for(j=1; j<n; j++){
                    k=a[j]+ans[j-1];
                    if(k==ave) ans[j]=0;
                    else if(k+1==ave){
                        if(a[(j+1)%n]) ans[j]=-1;
                        else break;
                    }
                    else if(k-1==ave){
                        ans[j]=1;
                    }
                    else break;
                }
                if(j==n&&a[0]-ans[0]+ans[n-1]==ave) break;
            }
            if(i==2) flag = 0;
        }
        if(flag==0){
            puts("NO");
        }
        else{
            puts("YES");
            num = 0;
            for(int i=0; i<n; i++) if(ans[i]) num++;
            printf("%d
", num);
            for(int i=0; i<n; i++){
                if(!ans[i]) continue;
                int u = i+1;
                int v = (i+1)%n+1;
                if(ans[i]==-1) swap(u, v);
                printf("%d %d
", u, v);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/spfa/p/7337673.html