zoukankan      html  css  js  c++  java
  • 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
    ");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
    ");continue;
    		}
    		kaishi=0;
    		for(i=1;i<=m;i++){
    			if(b[i].num==1){
    				kaishi=i;break;
    			}
    		}
    		if(kaishi==0){
    			printf("YES
    ");
    			printf("0
    ");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
    ");
    			printf("%d
    ",tot);
    			for(i=1;i<=tot;i++){
    				printf("%d %d
    ",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
    ");
    			printf("%d
    ",tot);
    			for(i=1;i<=tot;i++){
    				printf("%d %d
    ",c[i].l,c[i].r);
    			}
    			continue;
    		}
    		printf("NO
    ");
    	}
    	return 0;
    }
    /*
    100
    11
    1 -1 1 1 -1 0 1 -1 -1 1 -1
    */


  • 相关阅读:
    find 以及linux 和windows 文件互传
    27 关于Object类 -- equals()
    26 super关键字
    25 访问修饰符限定词
    24 继承 子类中方法重写
    23 static 关键字
    22 包(package)来解决不同包下同名文件的冲突问题
    21 封装(get,set方法)
    20 带参构造方法(this关键字)
    19 无参构造方法
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7047646.html
Copyright © 2011-2022 走看看