您的位置:首页 > 其它

hdu 5353 Average(贪心+构造)

2015-08-08 09:16 288 查看

题意:

有n个人组成一个环,相邻的两个人能互相给糖果,对于相邻的两个人而言,只能进行一次操作,要么x给y一个糖果,要么y给x一个糖果,要么不动,问能否经过一定的操作使得每个人的糖果数一样,并输出步骤。

解析:

很显然,如果当前的和sum不能被n除尽,那么肯定不能均分所以这种情况是”NO”。

然后可以计算出每个人的糖果,如果某人糖果和平均值的差距的绝对值>=2,那么也不可能平均分配。因为每条边只能走一次,而且每次只能给一个糖果,如果不管怎么索要,怎么给予,至多给2个,所以差距的绝对值>=2这种情况也是非法的。

然后就是判断环的情况,找到第一个> 0的人让他分发糖果,这时可以朝着前后两个方向走,两个方向都判断一次,如果第一个是>=2的,那么就分配给后面一个人一个糖果。

枚举前一个人对后一个人的三种操作,

然后这样第i个人必然对第i+1个人按照

1.少一个糖果就从下一个人手中拿一个

2.多一个就给一个给下一个人

然后判断最后的差距是否都是=0的,如果不是这种情况是false的。

mymy codecode

[code]#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#define pb push_back
typedef long long ll;
using namespace std;
const int N = 1e5 + 10;
struct Node {
    int a, b;
    Node(int a, int b) : a(a), b(b) {}
};

vector<Node> ans;
int n;
ll sum;
int A
, a
;

bool run(int dir, int st) {
    ans.clear();
    memcpy(a, A, sizeof(A));

    int flag = 0;
    int u, v;
    if(a[st] == 2) {
        u = st; v = (st - dir + n) % n;
        a[u]--, a[v]++;
        ans.pb(Node(u, v));
        flag = 1;
    }

    for(int i = 0; i < n - flag; i++) {
        u = (st + i*dir + n) % n;
        v = (st + (i+1)*dir + n) % n;

        if(a[u] > 0) {
            a[u]--, a[v]++;
            ans.pb(Node(u, v));
        }else if(a[u] < 0) {
            a[u]++, a[v]--;
            ans.pb(Node(v, u));
        }
        if(abs(a[v]) >= 2) return false;
    }

    for(int i = 0; i < n; i++) {
        if(a[i]) return false;
    }

    return true;
}

bool solve() {
    sum /= n;
    for(int i = 0; i < n; i++) A[i] -= sum;
    for(int i = 0; i < n; i++)
        if(abs(A[i]) > 2)
            return false;
    if(n == 2 && abs(A[0]) >= 2) {
        return false;
    }
    for(int i = 0; i < n; i++) {
        if(A[i] > 0) {
            if(run(-1, i)) return true;
            if(run(1, i)) return true;
            return false;
        }
    }
    return true;
}

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        ans.clear();
        sum = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i++) {
            scanf("%d", &A[i]);
            sum += A[i];
        }
        if(sum % n != 0) {
            puts("NO");
            continue;
        }
        if(!solve()) {
            puts("NO");
        }else {
            puts("YES");
            printf("%d\n", (int)ans.size());
            for(int i = 0; i < ans.size(); i++)
                printf("%d %d\n", ans[i].a+1, ans[i].b+1);
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: