HDU 5353 Average(平分值,求步聚)多校6

Average

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1948    Accepted Submission(s): 495

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 sodax
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 integerT,
indicating the number of test cases. For each test case:

The first contains an integer n(1≤n≤105),
the number of soda.

The next line contains n
integers a1,a2,…,an(0≤ai≤109),
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 integerm(0≤m≤n)
in the second line denoting the number of operations needed. Then each of the followingm
lines contain two integers x
and y(1≤x,y≤n),
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

Source

2015 Multi-University Training Contest 6

题意:有n个人围成一圈,每个人手上都有糖果数量,每个人可以给相邻的人一个糖果且只能给一次,问能否使得每个人手上的糖果一样多,如果可以输出YES 并输出操作步聚,如果不行输出NO。

解题:分情况:avg:平均值。a[ i ] :第 i 个人手上的糖果

1.a[1]-avg==2:向左右两给一个糖果,然后从1->n进行判断操作。

2.a[1]-avg==-2:从左右各得到一个糖果,然后............................

3.a[1]-avg==1:(1):向第2个人给一个糖果,然后............。(2)向第n个人给一个糖果,然后…………。

4.a[1]-avg==-1:(1):从第2个人得到一个糖果,然后……。(2)从第n个人得到一个糖果,然后……。

5.a[1]-avg==0:(1)第1个什么都不做,然后.......……。(2)从第2个人过寄一个糖果给第1个人,再第1个人又给了第n个人,然后…………。(3)从第n个人过寄一个糖果给第1个人,再第1个人又给了第2个人,然后…………。

当然,如果再某个情况找到了就可以直接输出。

#include<stdio.h>
#include<string.h>
#define ll __int64
const int N  = 100005;
struct EDG{
    int x,y;
};
int n,step;
ll a[N],b[N],avg;
EDG edg[N<<1];
void addEdg(int x,int y)
{
    edg[step].x=x;
    edg[step].y=y;
    step++;
}
bool findout(int l)
{
    while(l<=n){
        if(a[l]==avg){l++;continue;}
        if(l==n)return 0;
        if(a[l]>avg){
            if(a[l]-avg>1){
                return 0;
            }
            else{
                l++;
                a[l]++;
                a[l-1]--;
                addEdg(l-1 , l); //从左向右过一个
            }
        }
        else {
            if(avg-a[l]>1){
                return 0;
            }
            if(a[l+1]<avg){
                return 0;
            }
            l++; a[l]--; a[l-1]++;
            addEdg(l , l-1); //从右向左过一个
        }
    }

    return 1;
}
void print()
{
    printf("YES\n%d\n",step);
    for(int i=0; i<step; i++)
        printf("%d %d\n",edg[i].x,edg[i].y);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        avg=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%I64d",&b[i]);
            avg+=b[i] ;
        }
        if(avg%n!=0){
            printf("NO\n");continue;
        }
        avg/=n;
        step=0;
//因是一个圈,所以从第1 个分情况讨论,注意每次求完一轮把step 初始为0,我就是在这个WA了好多次
        if(b[1]-avg==2){
            for(int i=1; i<=n; i++)
            a[i]=b[i];
            a[1]--; a[2]++; addEdg(1 , 2);
            if(n>2){
                a[1]--;a[n]++; addEdg(1, n);
                if( findout(1) ){
                    print(); continue;
                }
            }
        }
        else if(b[1]-avg==-2){
            if(b[2]&&b[n]){
                for(int i=1; i<=n; i++)
                a[i]=b[i];
                a[1]++; a[2]--; addEdg(2 , 1);
                if(n>2){
                    a[1]++;a[n]--; addEdg(n, 1);
                    if( findout(1) ){
                        print(); continue;
                    }
                }
            }
        }
        else if(b[1]-avg==1){
            for(int i=1; i<=n; i++)
            a[i]=b[i];
            a[1]--; a[2]++; addEdg(1 , 2);
            if( findout(1) ){
                print(); continue;
            }
            step=0;
            for(int i=1; i<=n; i++)
            a[i]=b[i];
            a[1]--; a[n]++; addEdg(1 , n);
            if( findout(1) ){
                print(); continue;
            }
        }
        else if(b[1]-avg==-1){
            if(b[2]){
                for(int i=1; i<=n; i++)
                a[i]=b[i];
                a[1]++; a[2]--; addEdg(2 , 1);
                if( findout(1) ){
                    print(); continue;
                }
            }
            step=0;
            if(b[n]){
                for(int i=1; i<=n; i++)
                a[i]=b[i];
                a[1]++; a[n]--; addEdg(n , 1);
                if( findout(1) ){
                    print(); continue;
                }
            }
        }
        else if(avg==b[1]){
            for(int i=1; i<=n; i++)
            a[i]=b[i];
            if( findout(1) ){
                print(); continue;
            }
            step=0;
            if(b[2]){
                for(int i=1; i<=n; i++)
                a[i]=b[i];
                a[n]++; a[2]--; addEdg(1 , n); addEdg(2 , 1);
                if( findout(1) ){
                    print(); continue;
                }
            }
            step=0;
            if(b[n]){
                for(int i=1; i<=n; i++)
                a[i]=b[i];
                a[n]--; a[2]++;addEdg(1 , 2); addEdg(n , 1);
                if( findout(1) ){
                    print(); continue;
                }
            }
        }
        printf("NO\n");
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 20:37:25

HDU 5353 Average(平分值,求步聚)多校6的相关文章

HDU 5353 Average

题意:有n个人坐在圆桌上,每个人带着糖果若干,每次只能给旁边的人1科糖果,而且坐相邻的两个人最多只能给一次(要么你给我,要么我给你),问是否能将糖果平均分了. 思路:明显每个人最多只能多于平均值2个糖果,因为他只能分别往左和右边的人给1颗.而多于平均值1的人可以任意选1个方向,只要到最后所有人满足了即可.多余糖果超过3的.平均数是浮点型的都是无解. 在第i和第i+1个人之间建两条边(即无向边拆成2条有向边),分别从一方指向另一方.1和n也建两条.分两步: (1)将持有2个多余糖果的人先处理,用D

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): 517Special Judge Problem Description There are n soda sitting around a round table. soda are numbered fr

HDU 5353 Average 贪心

就是贪心啊,不知道为啥总是不过,总是WA 方法不对吗? 将数组扩展一倍,从左到右扫描,大于平均数就给右边的,小于就从右边拿,等于就不变,记录下操作类型. 大于2直接NO,应该是正确的算法吧,自己出了一些数据也都过了 1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include <iostream> 3 #include <cstdio> 4 #include <fstream>

HDU 2297 半平面交

Run Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 640    Accepted Submission(s): 181 Problem Description Since members of Wuhan University ACM Team are lack of exercise, they plan to particip

hdu 4418 高斯消元求期望

Time travel Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1480    Accepted Submission(s): 327 Problem Description Agent K is one of the greatest agents in a secret organization called Men in B

思维/构造 HDOJ 5353 Average

题目传送门 1 /* 2 思维/构造:赛后补的,当时觉得3题可以交差了,没想到这题也是可以做的.一看到这题就想到了UVA_11300(求最小交换数) 3 这题是简化版,只要判断行不行和行的方案就可以了,做法是枚举x[1],x[n]的所有可能,x[2~n-1]能递推出来 4 x[i]表示i给i+1的值(0/-1/1) 那么 a[i] - x[i] + x[i-1] == ave,详细看代码 5 */ 6 /**********************************************

hdu 3746 Cyclic Nacklace (KMP求最小循环节)

//len-next[len]为最小循环节的长度 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; char a[100010]; int next[100010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len) { if(j==-1||a[i]==a[j]) i

hdu 2262 高斯消元求期望

Where is the canteen Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1070    Accepted Submission(s): 298 Problem Description After a long drastic struggle with himself, LL decide to go for some

hdu 1008为何不对?求大神指导!

/*#include<iostream> using namespace std; int main(){ int n; while (cin >> n){ if (n == 0) break; else if (n > 0 && n < 100){ int sum=0, max,min; int *f = new int[n]; for (int i = 0; i < n; i++) cin >> f[i]; max = min =