ZOJ 2343(贪心)

Robbers

Time Limit: 5 Seconds       Memory Limit: 32768 KB       Special Judge

N robbers have robbed the bank. As the result of their crime they chanced to get M golden coins. Before the robbery the band has made an agreement that after the robbery i-th gangster would get Xi=Y of all money gained. However, it turned out that M may be not divisible by Y.

The problem which now should be solved by robbers is what to do with the coins. They would like to share them fairly. Let us suppose that i-th robber would get Ki coins. In this case unfairness of this fact is |Xi/Y - Ki/M|. The total unfairness is the sum of all particular unfairnesses. Your task as the leader of the gang is to spread money among robbers in such a way that the total unfairness is minimized.


This problem contains multiple test cases!

The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.

The output format consists of N output blocks. There is a blank line between output blocks.


Input

The first line of the input file contains numbers N, M and Y (1 <= N <= 1000, 1 <= M, Y <= 10000). N integer numbers follow - Xi (1 <= Xi <= 10000, sum of all Xi is Y).


Output

Output N integer numbers - Ki (sum of all Ki must be M), so that the total unfairness is minimal.


Sample Input

1

3 10 4
1 1 2


Sample Output

2 3 5


题解:题目大意:有N劫匪去抢银行,总计抢了M个金币,那么Y是什么呢?我理解的是就是每个劫匪做的贡献,当然啦,劫匪有劫匪的规矩,他们也要按劳分配。就是每个劫匪的|Xi/Y - Ki/M|的总和最小,也就是我理解的按劳分配,尽量让每个人都满意,所以贡献比和获得金钱数比的差值应该最小。

我的思路:既然是按劳分配,那就是劳的多就得的多,那么就好算了,那总的金钱数乘以他们各自的贡献比,如果除不尽的话,先给他整数部分的金钱,看他小数点后面是多少,当然要给那些小数点后面的数大的人先分给他一个金币。其实小数点后面的数就相当于一个权值。要按劳分配的话就要先分给权值大的人多余的金币。那么问题的答案就出来了。如果看不懂的话,可以去看看代码,应该可以看懂,就是一个简单的贪心。

下面附上代码:

#include<math.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
struct Node
{
    int a, id, ans; // a是这个人的贡献值, id是这个人的编号, ans是这个人最后得到的金钱数,b是权值,也就是小数点后面的数。
    double b;
}node[1005];
bool cmp1(Node x, Node y)
{
    return (x.b>y.b);
}
bool cmp2(Node x, Node y)
{
    return x.id<y.id;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int N, m, y, sum = 0;
        scanf("%d%d%d", &N, &m, &y);
        memset(node, 0, sizeof(node));
        for(int i = 0; i < N; i++)
        {
            scanf("%d", &node[i].a);
            node[i].id = i;
            double temp = m*node[i].a/y;
            node[i].ans = (int)temp;
            sum  += (int)temp;
            node[i].b = (double)m*node[i].a/y - temp;
        }
        sort(node,node+N, cmp1);
        for(int i = 0;i < N; i++)
        {
            if(sum>=m) break;
            node[i].ans++;
            sum++;
        }
        sort(node, node+N, cmp2);
        for(int i = 0; i < N; i++)
        {
            printf("%d", node[i].ans);
            if(i != N-1) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值