ZOJ 2343 Robbers(思路)

68 篇文章 0 订阅

Robbers

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

ps:能说这道题比赛时做了5个小时吗。。。智商感人啊!

思路:先利用比例求出每一个k[i],然后把k[i]分成整数和小数部分,并计算出总的整数部分的和s,然后按小数部分从大到小排序一下,接着遍历,对整数部分进行+1操作,直到s==m,最后再按原位置输出就好了

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define maxn 1010
struct node
{
    int x,pos;
    double y;
} q[maxn];
int a[maxn];

bool cmp1(node a,node b)
{
    if(a.y==b.y)
        return a.pos<b.pos;
    return a.y>b.y;
}

bool cmp2(node a,node b)
{
    return a.pos<b.pos;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,y;
        scanf("%d%d%d",&n,&m,&y);
        for(int i=1; i<=n; ++i)
            scanf("%d",&a[i]);
        double cc=m*1.0/y,tmp;
        int sum=0;
        for(int i=1; i<=n; ++i)
        {
            q[i].pos=i;
            tmp=a[i]*cc;
            q[i].x=(int)tmp;
            q[i].y=tmp-q[i].x;
            sum+=q[i].x;
        }
        sum=m-sum;
        sort(q+1,q+1+n,cmp1);
        for(int i=1; i<=n; ++i)
        {
            if(sum)
                ++q[i].x,--sum;
        }
        sort(q+1,q+1+n,cmp2);
        for(int i=1; i<=n; ++i)
            printf(i==n?"%d\n":"%d ",q[i].x);
        puts("");
    }
    return 0;
}

总结:果然是我们思路错了。。
看一下我们的思路吧,
算出每一个k[i]=m/y*x[i],先统计有多少个大于x.5的s1,多少个小于x.5的s2,多少个等于x.5的s3,然后遍历,如果是等于x.5的那就一替一个输出上界和下界,如果s1>s2,那么就从大于x.5并且最靠近x.5那里开始,输出他们的下界,直到最后s1和s2相等或相差为1。如果s2>s1,则相反

现在想想当时真是没考虑全面,智商差距啊!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值