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

本文介绍了一道关于糖果交换的模拟题解题思路,包括判断条件、解题策略和代码实现。通过计算糖果总数和平均分配,采用贪心算法解决相邻两人糖果交换的问题,确保所有糖果都能被合理分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值