HDU 5353 Average (2015年多校比赛第6场)

1.题目描述:点击打开链接

2.解题思路:本题属于一个简单的模拟题,然而在比赛时候考虑不周WA了。本题要求相邻的两个人可以交换一个糖果,且仅能交换一次。首先计算所有糖果的个数sum,如果sum不能整除n,那么肯定无解。否则,计算出平均值mean,然后让a[i]-=mean得到差值。此时可以利用贪心法来解决本题。令第i个人只和第i+1个人之间进行糖果交换:

如果差值为-1,则第i+1个人给第i个人一个糖果;

如果差值为0,则无操作;

如果差值为1,则第i个人给第i+1个人一个糖果;

此时要注意第1个人与第n个人之间糖果交换的情况。一共有三种:不交换,第1个人给第n个人一个糖果,第n个人给第1个人一个糖果。

3.代码:

vector<P>ans;
int m;
bool solve(int n,int*a)//第0个人到第n-1个人的“顺序”操作
{
    int ok=1;
    for(int i=0;i<n;i++)
    {
        if(abs(a[i]>1))return false;
        if(a[i]==-1)
        {
            ans.push_back(P(i+1,i));m++;
            a[i]++;a[i+1]--;
        }
        if(a[i]==1)
        {
            ans.push_back(P(i,i+1));m++;
            a[i]--;a[i+1]++;
        }
    }
    return true;
}

const int N=100000+10;
int a[N];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        ll sum=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
                sum+=a[i];
            }
        if(sum%n)puts("NO");
        else
        {
            int mean=sum/n;
            for(int i=0;i<n;i++)
                a[i]-=mean;
            int b[N];
            memcpy(b,a,sizeof(int)*n);
            int ok=1;
            m=0;ans.clear();
            if(!solve(n,b))//第0个人和第n-1个人之间不交换
            {
                memcpy(b,a,sizeof(int)*n);
                b[0]++;b[n-1]--;
                m=1;ans.clear();ans.push_back(P(n-1,0));
                if(!solve(n,a))//第0个人给第n-1个人一个糖果
                {
                    memcpy(b,a,sizeof(int)*n);
                    b[0]--;b[n-1]++;
                    m=1;ans.clear();ans.push_back(P(0,n-1));
                    if(!solve(n,a))ok=0;//第n-1个人给第0个人一个糖果
                }
            }
            if(ok)
            {
                puts("YES");
                printf("%d\n",m);
                for(int i=0;i<m;i++)
                    printf("%d %d\n",ans[i].first+1,ans[i].second+1);
            }
        }
    }
}

你可能感兴趣的:(模拟,多校)