ACM-ICPC 2017 北京 Cats and Fish

E - Cats and Fish

There are many homeless cats in PKU campus. They are all happy because the students in the cat club of PKU take good care of them. Li lei is one of the members of the cat club. He loves those cats very much. Last week, he won a scholarship and he wanted to share his pleasure with cats. So he bought some really tasty fish to feed them, and watched them eating with great pleasure. At the same time, he found an interesting question:

There are m fish and n cats, and it takes ci minutes for the ith cat to eat out one fish. A cat starts to eat another fish (if it can get one) immediately after it has finished one fish. A cat never shares its fish with other cats. When there are not enough fish left, the cat which eats quicker has higher priority to get a fish than the cat which eats slower. All cats start eating at the same time. Li Lei wanted to know, after x minutes, how many fish would be left.

Input
There are no more than 20 test cases.

For each test case:

The first line contains 3 integers: above mentioned m, n and x (0 < m <= 5000, 1 <= n <= 100, 0 <= x <= 1000).

The second line contains n integers c1,c2 … cn, ci means that it takes the ith cat ci minutes to eat out a fish ( 1<= ci <= 2000).

Output
For each test case, print 2 integers p and q, meaning that there are p complete fish(whole fish) and q incomplete fish left after x minutes.

Sample Input

2 1 1
1
8 3 5
1 3 4
4 5 1
5 4 3 2 1

Sample Output

1 0
0 1
0 3

题意:有n只猫吃m条鱼,每只猫吃鱼所需时间不同,吃完一条鱼才能吃下一条鱼。问经过x分钟后,还没被吃掉的且完好的鱼以及正在被吃且还未吃光的鱼分别有几条?

分析

共有三种情况:
1.m<n即鱼不够分配,则只需求正在被吃且还未吃光的鱼的数目。
对于时刻x,枚举每一只猫是否已经吃完仅有的鱼即可。
2.第x分钟时,鱼还未分配完,即存在没被吃掉的且完好的鱼,或鱼恰好分配完。
那么如何判断是否分配完呢?
只要计算num=x/time[1]+x/time[2]+...+x/time[n],若num>m,表示所有的鱼在第x分钟之前已经被分配完了,反之。
对于第二种情况,只需要枚举每只猫,计算x%time[i]不为0的个数ans即可得到正在被吃且还未吃光的鱼的数目。
所以答案为 m-num ans。
3.第x分钟时,鱼早已分配完了。
需要从x向前枚举出最后一个未分配完或恰好分配完的时刻pos。
将time数组从小到大排序,依次把剩下的鱼分配给吃鱼速度快的且已经吃完鱼的猫。
对于第x分钟,枚举第pos分钟时没有吃完鱼的猫,判断一下此时它们有没有吃完鱼即可。

其实这道题我想复杂了,队友用优先队列一下子就做出来了。
还是贴一下代码吧哈哈哈哈~

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
int t[110];
int g[110];
int main()
{
    int m,n,x;
    while(scanf("%d%d%d",&m,&n,&x)==3)
    {
        int num=0;int num_left=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&t[i]);
            num+=x/t[i];
            if(x%t[i])
            {
                 num++;
                 num_left++;
            }
        }
        sort(t,t+n);
        if(m<n)
        {
             int ans=0;
             for(int i=0;i<m;i++)
             {
                 if(x<t[i])
                    ans++;
             }
             printf("0 %d\n",ans);
             continue;
        }
        if(num>m)
        {
            int sum=num;
            int pos=x;
            while(sum>m&&pos>0)
            {
                sum=0;
                pos--;
                for(int i=0; i<n; i++)
                {
                    sum+=pos/t[i];
                    if(pos%t[i])
                    {
                        sum++;
                    }
                }
            }
            int xum=m-sum;
            for(int i=0;i<n;i++)
            {
                g[i]=pos;
                if(xum&&(pos%t[i]==0))
                {
                    g[i]++;
                    xum--;
                }
            }
            int ans=0;
            for(int i=0;i<n;i++)
            {
                if(g[i]%t[i])
                {
                    int cnt=g[i]/t[i];
                    if(x%t[i]&&x/t[i]==cnt)
                    {
                        ans++;
                    }
                }
            }
            printf("0 %d\n",ans);
        }
        else
            printf("%d %d\n",m-num,num_left);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值