zoukankan      html  css  js  c++  java
  • HDU 5353—— Average——————【贪心+枚举】

    Average

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 2069    Accepted Submission(s): 517
    Special Judge


    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个人围成一圈,每个人手上都有一定数量的糖果,相邻两个人可是给一个糖果,但是只能给一次,如x,y。x可以给y一个糖果,或者y可以给x一个糖果。也可以不操作,即都不给糖果。第一个人可以给第n个人一个糖果,或者第n个人给第一个人一个糖果,或不给。问是否可以通过给糖果这样的操作,让所有的人手中的糖果数量相同。如果可以,输出YES和需要多少次,同时输出路径。否则输出NO。

    解题思路:枚举第一个人对第二个人的三种操作,然后看第二个人跟average的差值,如果是-1,那么第二个人从第三个人手中拿走一个糖果,如果是1,那么第二个人给第三个人一个糖果,如果为零,则不操作。依次遍历到n。因为第n个人跟第1个人是可以操作的,所以我在操作第n个的时候,把对第一个人的操作放在了n+1的位置,c[1]+=c[n+1]判断第一个人的结果是否为零,如果为零,这说明可以,否则不可以。

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    const int maxn=1e5+200;
    typedef long long INT;
    int a[maxn] ,b[maxn] ,c[maxn];
    int f[3]={0,1,-1};
    int abs(int x){
        return x>0? x: -x;
    }
    struct Oper{
        int x,y;
    }oper[maxn];
    int main(){
    
        int t,n;
        scanf("%d",&t);
        while(t--){
    
            scanf("%d",&n);
            INT sum=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                sum+=a[i];
            }
            if(sum%n!=0){
                printf("NO
    ");continue;
            }else{
                if(n==1){   //1个的时候必然YES
                    printf("YES
    0
    ");
                    continue;
                }
                if(n==2){       //特判两个的情况
                    if(a[1]-a[2]==2){
                        printf("YES
    1
    ");
                        printf("1 2
    "); continue;
                    }else if(a[1]-a[2]==-2){
                        printf("YES
    1
    ");
                        printf("2 1
    ");continue;
                    }else if(a[1]==a[2]){
                        printf("YES
    ");
                        printf("0
    ");continue;
                    }
                }
                const int ave=sum/n;
                int flag=0;
                for(int i=1;i<=n;i++){
                    b[i]=a[i]-ave;  //把跟平均数的差值放在b数组中
                    if(abs(b[i])>2){
                        printf("NO
    ");
                        flag=1;
                        break;
                    }
                }
                if(flag)
                    continue;
                int num;
                b[n+1]=0;
                for(int k=0;k<3;k++){
                    num=0;  //num放错位置,wa了
                    for(int i=1;i<=n+1;i++){
                        c[i]=b[i];  
                    }
                    if(f[k]==1){
                        oper[num].x=2;
                        oper[num++].y=1;
                    }else if(f[k]== -1){
                        oper[num].x=1;
                        oper[num++].y=2;
                    }
                    //每次对c数组操作
                    c[1]+=f[k];
                    if(abs(c[1])>1 ){
                        continue;
                    }
                    c[2]-=f[k];
                    if(abs(c[2])>1){
                        continue;
                    }
                    int mark=0;
                    for(int i=2;i<=n;i++){  //遍历2-->n
                        if(c[i]==1){
                            c[i]-=1;
                            c[i+1]+=1;
                            if(i<n){
                                oper[num].x=i;
                                oper[num++].y=i+1;
                            }else{
                                oper[num].x=n;
                                oper[num++].y=1;
                            }
    
                        }else if(c[i]==-1){
                            c[i]+=1;
                            c[i+1]-=1;
                            if(i<n){
                                oper[num].x=i+1;
                                oper[num++].y=i;
                            }else{
                                oper[num].x=1;
                                oper[num++].y=n;
                            }
                        }
                        else if(abs(c[i])>1){
                            mark=1;
                            break;
                        }
                    }
                    if(mark){
                        continue;
                    }
                    if(c[1]+c[n+1]!=0){
                        continue;
                    }else{
                        flag=1;
                        break;
                    }
                }
                if(flag){
                    printf("YES
    ");
                    printf("%d
    ",num);
                    for(int i=0;i<num;i++){
                        printf("%d %d
    ",oper[i].x,oper[i].y);
                    }
                }else{
                    printf("NO
    ");
                }
    
            }
    
        }
        return 0;
    }
    

      

  • 相关阅读:
    [转]java 常用弹出框
    [转]ImageIcon icon 相对路径设置
    [转]『基本ASCII表和c语言运算表查询』
    [转]sqlmap技术手册
    [转]linux下怎么查看ssh的用户登录日志
    [转]Kali-linux安装之后的简单设置
    查看任意程序所连接的ip地址
    JS 闭包
    JS 中的 继承
    JS 原型的 理解
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4720135.html
Copyright © 2011-2022 走看看