Fair Division

Subject:

It’syour friend’s birthday, and you and some other people decided to buy him a copyof StarCraft II, because who wouldn’t want to have that?

Youagreed to divide the costs as fairly as possible. Since some of you have moremoney available than others, you also agreed that nobody has to pay more thanhe can afford. Every contribution will be a multiple of 1 cent, i.e., nobodycan pay fractions of a cent.

Everybodywrites down the maximum amount he is able to contribute. Taking into accountthese maximum amounts from everybody, you share the cost of the present asfairly as possible. That means, you minimize the largest distance of thecontributions to 1 n -th of the total cost. In case of a tie, minimize thesecond largest distance, and so on.

 Since the smallest unit of contribution is 1cent, there might be more than one possible division of the cost. In that case,persons with a higher maximum amount pay more. If there is still ambiguity,those who come first in the list pay more. Since you bought the present, it isyour task to figure out how much everybody has to pay (including you).


Input

      On the first line a positive integer: the number of test cases, at most 100.After that per test case: • One line with two integers p and n: the price ofthe present in cents (1 ≤ p ≤ 1 000 000) and the number of people (2 ≤ n ≤ 100)who contribute to the present (including you). • One line with n integers ai (1≤ ai ≤ 1 000 000), where ai is the maximum amount, in cents, that the i-thperson on the list is able to contribute. 


Output

Pertest case: • One line with n integers: the amounts each person has tocontribute according to the scheme. If the total cost cannot be dividedaccording to the above rules, the line must contain ‘IMPOSSIBLE’ instead. 

*************************************************************************************************************************

SampleInput

3

20 4

10 10 4 4

7 3

1 1 4

3 4 5

9 8 9 9 4

*************************************************************************************************************************

SampleOutput

6 6 4 4

IMPOSSIBLE

8 7 8 7 4


*************************************************************************************************************************

*************************************************************************************************************************

           贪心的题目。

思路如下:

       题目就是宰土豪,尽可能的让土豪去出钱,还要判断一个人能出多少的钱,还要去注意一下,平均的钱,每一次参与人数,因为一部分人付钱,付了全部,下次就可以不需要付了,他也就退出了付钱行列里面。此时的平均钱,就改变了,不是剩余出得钱去除以全部人了,因为他不要出了。

具体思路如下:

我们先排列一下,按照钱去排列,一样的按先后顺序,谁叫他先来,用一个数据表示,他出了多少钱,一个数据,表示他总共多少钱,一个数据表示,他的位置是在哪,(最后要进行输出的。)

 我们用一个money表示总钱,一个yl表示他出了多少的钱,一个zb表示他的座位。

现在开始出钱,如果他的总钱 减去 他的出的钱 小于或者等于 这次下来的平均的钱,那么他只出他剩下的钱,sum加上一次循环的收上来钱,

                                  反之,他要出这次的平均钱,sum加起来,yl加上他出过的钱,

结束条件就是土豪太多了,或者刚刚好的条件,刚刚好,他就直接退出了,我们看,不是刚刚好的情况,那么我们就是按照出现的顺序,让他们一个出一块钱,就ok了。退出循环。

*************************************************************************************************************************

*************************************************************************************************************************

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;


struct node
{
    int money;
    int zb;
    int yl;
} a[105];

bool cmp(node  n,node  m)
{
    if(n.money==m.money)
        return n.zb<m.zb;

    return n.money>m.money;
}

bool cmp2(node  n,node  m)
{
    return n.zb<m.zb;
}

int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int k,t1;
        scanf("%d%d",&k,&t1);
        long int sum =0;
        int t = t1;
        for(int i=0; i<t1; i++)
        {
            scanf("%d",&a[i].money);
            a[i].zb = i;
            a[i].yl = 0;
            sum+=a[i].money;
        }
        if(sum<k)
        {
            printf("IMPOSSIBLE\n");
        }
        else
        {
        	    sort(a,a+t1,cmp);
                while(k)
                {
                    int ave = k/t;
                    int people=t;
                    if(ave==0)
                    {
                    	//当钱数不够那些人平分的时候,就挑土豪出 
                        for(int i=0; i<k; i++)
                            a[i].yl++;
                        k=0;
                    }
                    else
                    {
                        sum = 0;
                        for(int i=0; i< people; i++)
                        {
                            //yl的钱,初始化为0,之后改变为你平均下来的钱。
                            //不够平均的钱,那么yl的钱为你现在的钱,,并且人数减一。
                            //表示你下次不要出了,原来的钱表示你已经出了的钱,
                            if(a[i].money-a[i].yl<=ave)
                            {
                                sum += a[i].money-a[i].yl;
                                a[i].yl = a[i].money;
                                t--;
                            }
                            //如果你是土豪,那么你应该扣平均的钱,并且原来的钱加上你现在的钱
                            //表示你已经出了这么多的钱
                            else
                            {
                                a[i].yl +=ave;
                                sum+=ave;
                            }
                        }
                        k -= sum;
                    }
                }
                sort(a,a+t1,cmp2);
                printf("%d",a[0].yl);
                for(int i=1; i<t1; i++)
                    printf(" %d",a[i].yl);
                printf("\n");
            }
    }
    return 0;
}
*************************************************************************************************************************

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值