hdu5353 Average

Problem Description
There are n soda sitting around a round table. soda are numbered from 1 to n and i-th soda is adjacent to (i+1)-th soda, 1-st soda is adjacent to n-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 x and y can do one of the following operations only once:
1. x-th soda gives y-th soda a candy if he has one;
2. y-th soda gives x-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 T, indicating the number of test cases. For each test case:

The first contains an integer n (1n105), the number of soda.
The next line contains n integers a1,a2,,an (0ai109), where ai denotes the candy i-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 m(0mn) in the second line denoting the number of operations needed. Then each of the following m lines contain two integers x and y (1x,yn), which means that x-th soda gives y-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个人均分蛋糕,刚开始每人都有a[i]块蛋糕,每个人有一次机会能把自己的一个苹果传给左边的人或者右边的人(注意是环状的),问能不能使最后每个人的蛋糕数都相同。

思路:先看总和能不能被n均分,不能均分就输出NO,如果能均分,算出平均值ave,把每一个a[i]变为a[i]-ave,如果a[i]的平均值大于等于3就输出NO,如果是2或者-2,就把它拆成两个1或者两个-1.

上面处理完后,就先找到第一个1的位置(如果找不到,说明都是0,直接输出YES),然后对于这个1,他只能分给右边的-1或者左边的-1,而且在遇到-1前不能再遇到1(可以画一下),当它走到原位置的时候,代表可行,如果中途就不可行就输出NO。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
#define maxn 100050
#define ll long long
struct node{
	int idx,num;
}b[2*maxn];
struct edge{
	int l,r;
}c[2*maxn];

int vis[2*maxn],tot,m;
ll a[2*maxn];
void daying(int st,int ed,int f)
{
	int i,j,k;
	if(f==2){
		if(st<ed){
			for(k=st;k<ed;k++){
				tot++;c[tot].l=b[k].idx;c[tot].r=b[k+1].idx;
			}
		}
		else{
			for(k=st;k<=m-1;k++){
				tot++;c[tot].l=b[k].idx;c[tot].r=b[k+1].idx;
			}
			tot++;c[tot].l=b[m].idx;c[tot].r=b[1].idx;
			for(k=1;k<ed;k++){
				tot++;c[tot].l=b[k].idx;c[tot].r=b[k+1].idx;
			}
		}
	}
	else if(f==1){
		if(st>ed){
			for(k=st;k>ed;k--){
				tot++;c[tot].l=b[k].idx;c[tot].r=b[k-1].idx;
			}
		}
		else{
			for(k=st;k>=2;k--){
				tot++;c[tot].l=b[k].idx;c[tot].r=b[k-1].idx;
			}
			tot++;c[tot].l=b[1].idx;c[tot].r=b[m].idx;
			for(k=m;k>ed;k--){
				tot++;c[tot].l=b[k].idx;c[tot].r=b[k-1].idx;
			}
		}
	}
}



int main()
{
	int i,j,T,flag,num,st,p,kaishi;
	ll sum,ave,n;
	scanf("%d",&T);
	while(T--)
	{
		sum=0;
		scanf("%lld",&n);
		for(i=1;i<=n;i++){
			scanf("%lld",&a[i]);
			sum+=a[i];
		}
		if(sum%n!=0){
			printf("NO\n");continue;
		}
		ave=sum/n;flag=1;
		m=0;
		for(i=1;i<=n;i++){
			a[i]=a[i]-ave;
			if(abs(a[i])>=3){
				flag=0;break;
			}
			if(a[i]==1 || a[i]==0 || a[i]==-1){
				m++;b[m].idx=i;b[m].num=a[i];
			}
			else{
				m++;b[m].idx=i;b[m].num=a[i]/2;
				m++;b[m].idx=i;b[m].num=a[i]/2;
			}
		}
		if(flag==0){
			printf("NO\n");continue;
		}
		kaishi=0;
		for(i=1;i<=m;i++){
			if(b[i].num==1){
				kaishi=i;break;
			}
		}
		if(kaishi==0){
			printf("YES\n");
			printf("0\n");continue;
		}
		tot=0;
		memset(vis,0,sizeof(vis));
		num=1;p=st=kaishi;vis[kaishi]=1;
		flag=1;
		while(1)  //往右方向找 
		{
			if(p==m){
				p=1;
			}
			else p++;
			if(vis[p]==1)break;
			vis[p]=1;
			if(b[p].num==0){
				continue;
			}
			if(num==0){
				st=p;
				num+=b[p].num;
				continue;
			}
			
			num+=b[p].num;
			if(abs(num)>=2){
				flag=0;break;
			}
			if(b[p].num==1){
				daying(p,st,1);
			}
			else{
				daying(st,p,2);
			}
			//st=p;
		}
		if(flag){
			printf("YES\n");
			printf("%d\n",tot);
			for(i=1;i<=tot;i++){
				printf("%d %d\n",c[i].l,c[i].r);
			}
			continue;
		}
		
		tot=0;
		memset(vis,0,sizeof(vis));
		num=1;p=st=kaishi;vis[kaishi]=1;
		flag=1;
		while(1)  //忘左方向找 
		{
			if(p==1){
				p=m;
			}
			else p--;
			if(vis[p]==1)break;
			vis[p]=1;
			if(b[p].num==0){
				continue;
			}
			if(num==0){
				st=p;
				num+=b[p].num;
				continue;
			}
			
			num+=b[p].num;
			if(abs(num)>=2){
				flag=0;break;
			}
			if(b[p].num==1){
				daying(p,st,2);
			}
			else{
				daying(st,p,1);
			}
		}
		if(flag){
			printf("YES\n");
			printf("%d\n",tot);
			for(i=1;i<=tot;i++){
				printf("%d %d\n",c[i].l,c[i].r);
			}
			continue;
		}
		printf("NO\n");
	}
	return 0;
}
/*
100
11
1 -1 1 1 -1 0 1 -1 -1 1 -1
*/


posted @ 2015-08-10 16:05  Herumw  阅读(104)  评论(0编辑  收藏  举报