要求:n个人围成一圈,每个人有若干个糖果,相邻的两人之间只可进行1次操作:A给B一个糖果、B给A一个糖果或不给糖果。问是否能使每个人糖果数相同。
方法:设置初值进行枚举。
1.首先看这题不好操作,因为每个人可向左操作也可向右操作。
2.一次循环从左到右判断两个人之间进行什么操作,这样一次循环就包括了一个人与左右两个人的操作,假设B左边是A,B右边是C,不好判断B与A和B与C进行什么操作,先分析A与B,再分析B与C即可。
3.第2步需要一个初值才能启动判断,假设从第1个人开始判断,因为第1个人和第2个人、第n个人均有操作的可能,所以开始无法判断第1个人和第2个人进行什么操作,但是第1个人和第2个人之间只有三种操作的可能。枚举3种可能作为第1个人和第2个人的操作初值,因此左边处理过了,依次向右判断。
4.重点是初值的枚举!!!!!!
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long a[100001],b[100001];
struct ab
{
int x,y;
};
ab cd[100001];
int main()
{
int t,n,i,j,k,flag;
long long sum1,aver,cnt,max1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
sum1=0;
max1=-1;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum1+=a[i];
max1=max(max1,a[i]);
}
if(double(sum1)/double(n)!=sum1/n)
{
printf("NO\n");
continue;
}
aver=sum1/n;
if(max1==aver)
{
printf("YES\n0\n");
continue;
}
for(k=-1;k<=1;k++)
{
memcpy(b,a,sizeof(a));
flag=1;
cnt=0;
b[0]-=k;
b[1]+=k;
if(k==1)
{
cd[cnt].x=1;
cd[cnt].y=2;
cnt++;
}
if(k==-1)
{
cd[cnt].x=2;
cd[cnt].y=1;
cnt++;
}
for(i=1;i<n;i++)
{
if(b[i]==aver) continue;
else if(b[i]-aver>0)
{
b[i]-=1;
b[(i+1)%n]+=1;
cd[cnt].x=i+1;
cd[cnt].y=(i+1)%n+1;
cnt++;
}
else if(b[i]-aver<0)
{
b[i]+=1;
b[(i+1)%n]-=1;
cd[cnt].x=(i+1)%n+1;
cd[cnt].y=i+1;
cnt++;
}
}
for(i=0;i<n;i++)
if(b[i]!=aver) flag=0;
if(flag) break;
}
if(!flag)
{
printf("NO\n");
continue;
}
printf("YES\n");
printf("%d\n",cnt);
for(i=0;i<cnt;i++)
printf("%d %d\n",cd[i].x,cd[i].y);
}
}